From 14b4e966ddd77b85a3e15f6487bffdaec7d1b13f Mon Sep 17 00:00:00 2001 From: purplerain Date: Wed, 13 Mar 2024 18:28:34 +0000 Subject: [PATCH] sync with OpenBSD -current --- regress/sys/netinet6/frag6/LICENSE | 2 +- regress/sys/netinet6/frag6/Makefile | 8 +- regress/sys/netinet6/frag6/frag6_oversize.py | 65 +++++ .../sys/netinet6/frag6/frag6_unfragsize.py | 77 ++++++ regress/usr.bin/lastcomm/gadget.S | 6 +- sys/arch/arm64/arm64/machdep.c | 3 +- sys/conf/GENERIC | 4 +- sys/dev/dt/dt_prov_profile.c | 6 +- usr.bin/tmux/tmux.1 | 16 +- usr.sbin/btrace/ksyms.c | 248 ++++++++++-------- 10 files changed, 311 insertions(+), 124 deletions(-) create mode 100644 regress/sys/netinet6/frag6/frag6_oversize.py create mode 100644 regress/sys/netinet6/frag6/frag6_unfragsize.py diff --git a/regress/sys/netinet6/frag6/LICENSE b/regress/sys/netinet6/frag6/LICENSE index 866739d7e..95f9e99b4 100644 --- a/regress/sys/netinet6/frag6/LICENSE +++ b/regress/sys/netinet6/frag6/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2012-2020 Alexander Bluhm +Copyright (c) 2012-2024 Alexander Bluhm Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/regress/sys/netinet6/frag6/Makefile b/regress/sys/netinet6/frag6/Makefile index 8d1436c4f..cec85216c 100644 --- a/regress/sys/netinet6/frag6/Makefile +++ b/regress/sys/netinet6/frag6/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.29 2023/09/08 21:15:02 bluhm Exp $ +# $OpenBSD: Makefile,v 1.30 2024/03/12 21:31:29 bluhm Exp $ # The following ports must be installed: # @@ -88,7 +88,11 @@ stamp-pf: addr.py pf.conf FRAG6_SCRIPTS !!= cd ${.CURDIR} && ls -1 frag6*.py run-stack-frag6_queuelimit.py: - # the stack does not limit the amount of fragments during reassembly + # stack does not limit the amount of fragments during reassembly + @echo DISABLED + +run-pf-frag6_oversize.py run-pf-frag6_unfragsize.py: + # pf does not send icmp parameter problem, so test does not work @echo DISABLED run-stack-frag6_doubleatomic.py: addr.py stamp-stack diff --git a/regress/sys/netinet6/frag6/frag6_oversize.py b/regress/sys/netinet6/frag6/frag6_oversize.py new file mode 100644 index 000000000..3fbdfcae5 --- /dev/null +++ b/regress/sys/netinet6/frag6/frag6_oversize.py @@ -0,0 +1,65 @@ +#!/usr/local/bin/python3 + +print("ping6 fragments in total larger than IP maximum packet") + +# |---------| +# |--------| +# ... ... +# |--------| + +import os +from addr import * +from scapy.all import * + +pid=os.getpid() +eid=pid & 0xffff +payload=b"ABCDEFGHIJKLMNOP" +packet=IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/ \ + ICMPv6EchoRequest(id=eid, data=4095*payload) +plen=IPv6(raw(packet)).plen +print("plen=%u" % (plen)) +if plen != 0xfff8: + print("PLEN!=%u" % (0xfff8)) + exit(2) +bytes=bytes(packet)+b"12345678" + +frag=[] +fid=pid & 0xffffffff +frag.append(IPv6ExtHdrFragment(nh=58, id=fid, m=1)/bytes[40:40+2**10]) +off=2**7 +while off < 2**13: + frag.append(IPv6ExtHdrFragment(nh=58, id=fid, offset=off)/ \ + bytes[40+off*8:40+off*8+2**10]) + off+=2**7 +eth=[] +for f in frag: + pkt=IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/f + eth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/pkt) + +if os.fork() == 0: + time.sleep(1) + sendp(eth, iface=LOCAL_IF) + os._exit(0) + +ans=sniff(iface=LOCAL_IF, timeout=3, filter= + "ip6 and src "+REMOTE_ADDR6+" and dst "+LOCAL_ADDR6+" and icmp6") +for a in ans: + print("type %d" % (a.payload.payload.type)) + print("icmp %s" % (icmp6types[a.payload.payload.type])) + if a and a.type == ETH_P_IPV6 and \ + ipv6nh[a.payload.nh] == 'ICMPv6' and \ + icmp6types[a.payload.payload.type] == 'Parameter problem': + print("code=%u" % (a.payload.payload.code)) + # 0: 'erroneous header field encountered' + if a.payload.payload.code != 0: + print("WRONG PARAMETER PROBLEM CODE") + exit(1) + ptr=a.payload.payload.ptr + print("ptr=%u" % (ptr)) + # 42: sizeof IPv6 header + offset in fragment header + if ptr != 42: + print("PTR!=%u" % (ptr)) + exit(1) + exit(0) +print("NO ICMP PARAMETER PROBLEM") +exit(2) diff --git a/regress/sys/netinet6/frag6/frag6_unfragsize.py b/regress/sys/netinet6/frag6/frag6_unfragsize.py new file mode 100644 index 000000000..05585d7d9 --- /dev/null +++ b/regress/sys/netinet6/frag6/frag6_unfragsize.py @@ -0,0 +1,77 @@ +#!/usr/local/bin/python3 + +print("ping6 fragments with options total larger than IP maximum packet") + +# |--------| +# ... ... +# |--------| +# drop first fragment with ECN conflict, reinsert with longer unfrag part +# |---------| +# HopByHop|---------| + +import os +from addr import * +from scapy.all import * + +pid=os.getpid() +eid=pid & 0xffff +payload=b"ABCDEFGHIJKLMNOP" +packet=IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/ \ + ICMPv6EchoRequest(id=eid, data=4095*payload) +plen=IPv6(raw(packet)).plen +print("plen=%u" % (plen)) +if plen != 0xfff8: + print("PLEN!=%u" % (0xfff8)) + exit(2) +bytes=bytes(packet) + +frag=[] +fid=pid & 0xffffffff +off=2**7 +while off < 2**13: + frag.append(IPv6ExtHdrFragment(nh=58, id=fid, offset=off)/ \ + bytes[40+off*8:40+off*8+2**10]) + off+=2**7 +eth=[] +for f in frag: + pkt=IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/f + eth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/pkt) + +# first fragment with ECN to be dropped +eth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/ + IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6, tc=3)/ + IPv6ExtHdrFragment(nh=58, id=fid, m=1)/bytes[40:40+2**10]) + +# resend first fragment with unfragmentable part too long for IP plen +eth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/ + IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/ + IPv6ExtHdrHopByHop(options=PadN(optdata="\0"*4))/ + IPv6ExtHdrFragment(nh=58, id=fid, m=1)/bytes[40:40+2**10]) + +if os.fork() == 0: + time.sleep(1) + sendp(eth, iface=LOCAL_IF) + os._exit(0) + +ans=sniff(iface=LOCAL_IF, timeout=3, filter= + "ip6 and src "+REMOTE_ADDR6+" and dst "+LOCAL_ADDR6+" and icmp6") +for a in ans: + print("type %d" % (a.payload.payload.type)) + print("icmp %s" % (icmp6types[a.payload.payload.type])) + if a and a.type == ETH_P_IPV6 and \ + ipv6nh[a.payload.nh] == 'ICMPv6' and \ + icmp6types[a.payload.payload.type] == 'Parameter problem': + print("code=%u" % (a.payload.payload.code)) + # 0: 'erroneous header field encountered' + if a.payload.payload.code != 0: + print("WRONG PARAMETER PROBLEM CODE") + exit(1) + ptr=a.payload.payload.ptr + print("ptr=%u" % (ptr)) + # 42: sizeof IPv6 header + offset in fragment header + if ptr != 42: + print("PTR!=%u" % (ptr)) + exit(1) + exit(0) +print("NO ICMP PARAMETER PROBLEM") +exit(2) diff --git a/regress/usr.bin/lastcomm/gadget.S b/regress/usr.bin/lastcomm/gadget.S index dc0ca6cc8..8c91db6ed 100644 --- a/regress/usr.bin/lastcomm/gadget.S +++ b/regress/usr.bin/lastcomm/gadget.S @@ -1,4 +1,4 @@ -/* $OpenBSD: gadget.S,v 1.1 2023/01/09 11:50:01 anton Exp $ */ +/* $OpenBSD: gadget.S,v 1.2 2024/03/13 11:18:42 kettenis Exp $ */ #include #include @@ -12,11 +12,13 @@ .type gadget_getpid,_ASM_TYPE_FUNCTION gadget_getpid: #if defined(__amd64__) + endbr64 mov $SYS_getpid, %eax syscall ret #elif defined(__aarch64__) - ldr x8, #SYS_getpid + bti c + mov x8, #SYS_getpid svc 0 dsb nsh isb diff --git a/sys/arch/arm64/arm64/machdep.c b/sys/arch/arm64/arm64/machdep.c index fc1df710f..ba1fcf72f 100644 --- a/sys/arch/arm64/arm64/machdep.c +++ b/sys/arch/arm64/arm64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.86 2024/02/21 01:45:14 dlg Exp $ */ +/* $OpenBSD: machdep.c,v 1.87 2024/03/13 14:57:08 kettenis Exp $ */ /* * Copyright (c) 2014 Patrick Wildt * Copyright (c) 2021 Mark Kettenis @@ -366,6 +366,7 @@ cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, return sysctl_rdquad(oldp, oldlenp, newp, value); case CPU_ID_AA64PFR1: value = 0; + value |= cpu_id_aa64pfr1 & ID_AA64PFR1_BT_MASK; value |= cpu_id_aa64pfr1 & ID_AA64PFR1_SBSS_MASK; return sysctl_rdquad(oldp, oldlenp, newp, value); case CPU_ID_AA64ISAR2: diff --git a/sys/conf/GENERIC b/sys/conf/GENERIC index ac7ab88e7..3ab6eb1bc 100644 --- a/sys/conf/GENERIC +++ b/sys/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.294 2024/03/10 13:25:10 jsg Exp $ +# $OpenBSD: GENERIC,v 1.295 2024/03/13 14:43:31 bluhm Exp $ # # Machine-independent option; used by all architectures for their # GENERIC kernel @@ -16,7 +16,7 @@ option KMEMSTATS # collect malloc(9) statistics option PTRACE # ptrace(2) system call #option KVA_GUARDPAGES # slow virtual address recycling (+ guarding) -#option POOL_DEBUG # pool corruption detection +option POOL_DEBUG # pool corruption detection #option VFSLCKDEBUG # VFS locking checks option CRYPTO # Cryptographic framework diff --git a/sys/dev/dt/dt_prov_profile.c b/sys/dev/dt/dt_prov_profile.c index 1388770fb..26972585d 100644 --- a/sys/dev/dt/dt_prov_profile.c +++ b/sys/dev/dt/dt_prov_profile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dt_prov_profile.c,v 1.6 2024/02/09 17:42:18 cheloha Exp $ */ +/* $OpenBSD: dt_prov_profile.c,v 1.7 2024/03/13 13:13:57 bluhm Exp $ */ /* * Copyright (c) 2019 Martin Pieuchot @@ -53,13 +53,13 @@ int dt_prov_profile_init(void) { dtpp_profile = dt_dev_alloc_probe("hz", "97", &dt_prov_profile); - dt_dev_register_probe(dtpp_profile); if (dtpp_profile == NULL) return 0; + dt_dev_register_probe(dtpp_profile); dtpp_interval = dt_dev_alloc_probe("hz", "1", &dt_prov_interval); - dt_dev_register_probe(dtpp_interval); if (dtpp_interval == NULL) return 1; + dt_dev_register_probe(dtpp_interval); return 2; } diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index 43fbad273..b0f6a0d58 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.936 2024/02/13 08:10:23 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.937 2024/03/13 11:25:50 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott .\" @@ -14,7 +14,7 @@ .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: February 13 2024 $ +.Dd $Mdocdate: March 13 2024 $ .Dt TMUX 1 .Os .Sh NAME @@ -1036,9 +1036,17 @@ The following commands are available to manage clients and sessions: .D1 Pq alias: Ic attach If run from outside .Nm , -create a new client in the current terminal and attach it to +attach to +.Ar target-session +in the current terminal. +.Ar target-session +must already exist - to create a new session, see the +.Ic new-session +command (with +.Fl A +to create or attach). +If used from inside, switch the currently attached session to .Ar target-session . -If used from inside, switch the current client. If .Fl d is specified, any other clients attached to the session are detached. diff --git a/usr.sbin/btrace/ksyms.c b/usr.sbin/btrace/ksyms.c index b96487792..27542efd3 100644 --- a/usr.sbin/btrace/ksyms.c +++ b/usr.sbin/btrace/ksyms.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ksyms.c,v 1.6 2023/11/10 18:56:21 jasper Exp $ */ +/* $OpenBSD: ksyms.c,v 1.7 2024/03/12 17:22:24 cheloha Exp $ */ /* * Copyright (c) 2016 Martin Pieuchot @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -30,60 +31,149 @@ #include "btrace.h" -struct syms { - int fd; - Elf *elf; - Elf_Scn *symtab; - size_t strtabndx, nsymb; +struct sym { + char *sym_name; + unsigned long sym_value; /* from st_value */ + unsigned long sym_size; /* from st_size */ }; -int kelf_parse(struct syms *); +struct syms { + struct sym *table; + size_t nsymb; +}; + +int sym_compare_search(const void *, const void *); +int sym_compare_sort(const void *, const void *); struct syms * kelf_open(const char *path) { - struct syms *syms; - int error; + char *name; + Elf *elf; + Elf_Data *data = NULL; + Elf_Scn *scn = NULL, *symtab; + GElf_Sym sym; + GElf_Shdr shdr; + size_t i, shstrndx, strtabndx = SIZE_MAX, symtab_size; + unsigned long diff; + struct sym *tmp; + struct syms *syms = NULL; + int fd; if (elf_version(EV_CURRENT) == EV_NONE) errx(1, "elf_version: %s", elf_errmsg(-1)); - if ((syms = calloc(1, sizeof(*syms))) == NULL) - err(1, NULL); - - syms->fd = open(path, O_RDONLY); - if (syms->fd == -1) { + fd = open(path, O_RDONLY); + if (fd == -1) { warn("open: %s", path); - free(syms); return NULL; } - if ((syms->elf = elf_begin(syms->fd, ELF_C_READ, NULL)) == NULL) { + if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { warnx("elf_begin: %s", elf_errmsg(-1)); goto bad; } - if (elf_kind(syms->elf) != ELF_K_ELF) + if (elf_kind(elf) != ELF_K_ELF) goto bad; - error = kelf_parse(syms); - if (error) + if (elf_getshdrstrndx(elf, &shstrndx) != 0) { + warnx("elf_getshdrstrndx: %s", elf_errmsg(-1)); + goto bad; + } + + while ((scn = elf_nextscn(elf, scn)) != NULL) { + if (gelf_getshdr(scn, &shdr) != &shdr) { + warnx("elf_getshdr: %s", elf_errmsg(-1)); + goto bad; + } + if ((name = elf_strptr(elf, shstrndx, shdr.sh_name)) == NULL) { + warnx("elf_strptr: %s", elf_errmsg(-1)); + goto bad; + } + if (strcmp(name, ELF_SYMTAB) == 0 && + shdr.sh_type == SHT_SYMTAB && shdr.sh_entsize != 0) { + symtab = scn; + symtab_size = shdr.sh_size / shdr.sh_entsize; + } + if (strcmp(name, ELF_STRTAB) == 0 && + shdr.sh_type == SHT_STRTAB) { + strtabndx = elf_ndxscn(scn); + } + } + if (symtab == NULL) { + warnx("%s: %s: section not found", path, ELF_SYMTAB); + goto bad; + } + if (strtabndx == SIZE_MAX) { + warnx("%s: %s: section not found", path, ELF_STRTAB); + goto bad; + } + + data = elf_rawdata(symtab, data); + if (data == NULL) goto bad; - return syms; + if ((syms = calloc(1, sizeof(*syms))) == NULL) + err(1, NULL); + syms->table = calloc(symtab_size, sizeof *syms->table); + if (syms->table == NULL) + err(1, NULL); + for (i = 0; i < symtab_size; i++) { + if (gelf_getsym(data, i, &sym) == NULL) + continue; + if (GELF_ST_TYPE(sym.st_info) != STT_FUNC) + continue; + name = elf_strptr(elf, strtabndx, sym.st_name); + if (name == NULL) + continue; + syms->table[syms->nsymb].sym_name = strdup(name); + if (syms->table[syms->nsymb].sym_name == NULL) + err(1, NULL); + syms->table[syms->nsymb].sym_value = sym.st_value; + syms->table[syms->nsymb].sym_size = sym.st_size; + syms->nsymb++; + } + tmp = reallocarray(syms->table, syms->nsymb, sizeof *syms->table); + if (tmp == NULL) + err(1, NULL); + syms->table = tmp; + + /* Sort symbols in ascending order by address. */ + qsort(syms->table, syms->nsymb, sizeof *syms->table, sym_compare_sort); + + /* + * Some functions, particularly those written in assembly, have an + * st_size of zero. We can approximate a size for these by assuming + * that they extend from their st_value to that of the next function. + */ + for (i = 0; i < syms->nsymb; i++) { + if (syms->table[i].sym_size != 0) + continue; + /* Can't do anything for the last symbol. */ + if (i + 1 == syms->nsymb) + continue; + diff = syms->table[i + 1].sym_value - syms->table[i].sym_value; + syms->table[i].sym_size = diff; + } bad: - kelf_close(syms); - return NULL; + elf_end(elf); + close(fd); + return syms; } void kelf_close(struct syms *syms) { + size_t i; + if (syms == NULL) return; - elf_end(syms->elf); - close(syms->fd); + + for (i = 0; i < syms->nsymb; i++) + free(syms->table[i].sym_name); + free(syms->table); free(syms); } @@ -91,106 +181,46 @@ int kelf_snprintsym(struct syms *syms, char *str, size_t size, unsigned long pc, unsigned long off) { - GElf_Sym sym; - Elf_Data *data = NULL; - Elf_Addr offset, bestoff = 0; - size_t i, bestidx = 0; - char *name; - int cnt; + struct sym key = { .sym_value = pc + off }; + struct sym *entry; + Elf_Addr offset; if (syms == NULL) goto fallback; - data = elf_rawdata(syms->symtab, data); - if (data == NULL) + entry = bsearch(&key, syms->table, syms->nsymb, sizeof *syms->table, + sym_compare_search); + if (entry == NULL) goto fallback; - for (i = 0; i < syms->nsymb; i++) { - if (gelf_getsym(data, i, &sym) == NULL) - continue; - if (GELF_ST_TYPE(sym.st_info) != STT_FUNC) - continue; - if (pc >= sym.st_value + off) { - if (pc < (sym.st_value + off + sym.st_size)) - break; - /* Workaround for symbols w/o size, usually asm ones. */ - if (sym.st_size == 0 && sym.st_value + off > bestoff) { - bestidx = i; - bestoff = sym.st_value + off; - } - } - } - - if (i == syms->nsymb) { - if (bestidx == 0 || gelf_getsym(data, bestidx, &sym) == NULL) - goto fallback; - } - - name = elf_strptr(syms->elf, syms->strtabndx, sym.st_name); - if (name != NULL) - cnt = snprintf(str, size, "\n%s", name); - else - cnt = snprintf(str, size, "\n0x%llx", sym.st_value); - if (cnt < 0) - return cnt; - - offset = pc - (sym.st_value + off); + offset = pc - (entry->sym_value + off); if (offset != 0) { - int l; - - l = snprintf(str + cnt, size > (size_t)cnt ? size - cnt : 0, - "+0x%llx", (unsigned long long)offset); - if (l < 0) - return l; - cnt += l; + return snprintf(str, size, "\n%s+0x%llx", + entry->sym_name, (unsigned long long)offset); } - return cnt; + return snprintf(str, size, "\n%s", entry->sym_name); fallback: return snprintf(str, size, "\n0x%lx", pc); } int -kelf_parse(struct syms *syms) +sym_compare_sort(const void *ap, const void *bp) { - GElf_Shdr shdr; - Elf_Scn *scn, *scnctf; - char *name; - size_t shstrndx; + const struct sym *a = ap, *b = bp; - if (elf_getshdrstrndx(syms->elf, &shstrndx) != 0) { - warnx("elf_getshdrstrndx: %s", elf_errmsg(-1)); - return 1; - } - - scn = scnctf = NULL; - while ((scn = elf_nextscn(syms->elf, scn)) != NULL) { - if (gelf_getshdr(scn, &shdr) != &shdr) { - warnx("elf_getshdr: %s", elf_errmsg(-1)); - return 1; - } - - if ((name = elf_strptr(syms->elf, shstrndx, - shdr.sh_name)) == NULL) { - warnx("elf_strptr: %s", elf_errmsg(-1)); - return 1; - } - - if (strcmp(name, ELF_SYMTAB) == 0 && - shdr.sh_type == SHT_SYMTAB && shdr.sh_entsize != 0) { - syms->symtab = scn; - syms->nsymb = shdr.sh_size / shdr.sh_entsize; - } - - if (strcmp(name, ELF_STRTAB) == 0 && - shdr.sh_type == SHT_STRTAB) { - syms->strtabndx = elf_ndxscn(scn); - } - } - - if (syms->symtab == NULL) - warnx("symbol table not found"); - - return 0; + if (a->sym_value < b->sym_value) + return -1; + return a->sym_value > b->sym_value; +} + +int +sym_compare_search(const void *keyp, const void *entryp) +{ + const struct sym *entry = entryp, *key = keyp; + + if (key->sym_value < entry->sym_value) + return -1; + return key->sym_value >= entry->sym_value + entry->sym_size; }