diff --git a/bin/ps/print.c b/bin/ps/print.c index 1704522b7..b493e37bd 100644 --- a/bin/ps/print.c +++ b/bin/ps/print.c @@ -1,4 +1,4 @@ -/* $OpenBSD: print.c,v 1.86 2023/03/08 14:47:02 tobhe Exp $ */ +/* $OpenBSD: print.c,v 1.87 2024/01/16 19:08:37 deraadt Exp $ */ /* $NetBSD: print.c,v 1.27 1995/09/29 21:58:12 cgd Exp $ */ /*- @@ -303,6 +303,10 @@ printstate(const struct pinfo *pi, VARENT *ve) *cp++ = '+'; if (kp->p_psflags & PS_PLEDGE) *cp++ = 'p'; + if (kp->p_psflags & PS_PIN) + *cp++ = 'l'; + if (kp->p_psflags & PS_LIBCPIN) + *cp++ = 'L'; if (kp->p_eflag & EPROC_UNVEIL) { if (kp->p_eflag & EPROC_LKUNVEIL) *cp++ = 'U'; diff --git a/bin/ps/ps.1 b/bin/ps/ps.1 index 3abfd34f3..f28a3c68a 100644 --- a/bin/ps/ps.1 +++ b/bin/ps/ps.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ps.1,v 1.131 2023/11/10 09:17:02 kn Exp $ +.\" $OpenBSD: ps.1,v 1.132 2024/01/16 19:08:37 deraadt Exp $ .\" $NetBSD: ps.1,v 1.16 1996/03/21 01:36:28 jtc Exp $ .\" .\" Copyright (c) 1980, 1990, 1991, 1993, 1994 @@ -30,7 +30,7 @@ .\" .\" @(#)ps.1 8.3 (Berkeley) 4/18/94 .\" -.Dd $Mdocdate: November 10 2023 $ +.Dd $Mdocdate: January 16 2024 $ .Dt PS 1 .Os .Sh NAME @@ -359,6 +359,9 @@ PS_EXECPLEDGE 0x00400000 has exec pledges PS_ORPHAN 0x00800000 process is on an orphan list PS_CHROOT 0x01000000 process is chrooted PS_NOBTCFI 0x02000000 no Branch Target CFI +PS_PIN 0x08000000 ld.so or static executable that + has syscalls pinned +PS_LIBCPIN 0x10000000 libc.so has syscalls pinned .Ed .It Cm re Core residency time (in seconds; 127 = infinity). @@ -475,6 +478,11 @@ scheduling priority. .It p The process has called .Xr pledge 2 . +.It l +.Xr ld.so 1 +or a static executable has syscall pinning. +.It L +libc.so has syscall pinning. .\" .It S .\" The process has asked for FIFO .\" page replacement diff --git a/libexec/ld.so/library.c b/libexec/ld.so/library.c index b203d4fce..bfff01fe5 100644 --- a/libexec/ld.so/library.c +++ b/libexec/ld.so/library.c @@ -1,4 +1,4 @@ -/* $OpenBSD: library.c,v 1.93 2023/12/19 16:13:22 deraadt Exp $ */ +/* $OpenBSD: library.c,v 1.94 2024/01/16 19:07:31 deraadt Exp $ */ /* * Copyright (c) 2002 Dale Rahn @@ -99,7 +99,7 @@ elf_object_t * _dl_tryload_shlib(const char *libname, int type, int flags, int nodelete) { struct range_vector imut, mut; - int libfile, i; + int libfile, libc = -1, i; struct load_list *next_load, *load_list = NULL; Elf_Addr maxva = 0, minva = ELF_NO_ADDR; Elf_Addr libaddr, loff, align = _dl_pagesz - 1; @@ -109,8 +109,8 @@ _dl_tryload_shlib(const char *libname, int type, int flags, int nodelete) size_t exec_size = 0; Elf_Dyn *dynp = NULL; Elf_Ehdr *ehdr; - Elf_Phdr *phdp; - Elf_Phdr *ptls = NULL; + Elf_Phdr *phdp, *ptls = NULL; + Elf_Phdr *syscall_phdp = NULL; struct stat sb; #define powerof2(x) ((((x) - 1) & (x)) == 0) @@ -139,7 +139,6 @@ _dl_tryload_shlib(const char *libname, int type, int flags, int nodelete) if (flags & DF_1_NOOPEN) { _dl_close(libfile); return NULL; - } _dl_read(libfile, hbuf, sizeof(hbuf)); @@ -316,11 +315,30 @@ _dl_tryload_shlib(const char *libname, int type, int flags, int nodelete) _dl_push_range_size(&mut, phdp->p_vaddr + loff, phdp->p_memsz); break; + case PT_OPENBSD_SYSCALLS: + syscall_phdp = phdp; + break; default: break; } } + libc = _dl_islibc(dynp, loff); + if (libc) { + if (syscall_phdp) + _dl_pin(libfile, syscall_phdp, (void *)libaddr, + (size_t)((exec_start + exec_size) - libaddr), + exec_start, exec_size); + + /* + * XXX msyscall() can be removed once pinsyscalls() + * is fully operational + */ + /* Request permission for system calls in libc.so's text segment */ + if (_dl_msyscall(exec_start, exec_size) == -1) + _dl_printf("msyscall %lx %lx error\n", + exec_start, exec_size); + } _dl_close(libfile); dynp = (Elf_Dyn *)((unsigned long)dynp + loff); @@ -328,8 +346,6 @@ _dl_tryload_shlib(const char *libname, int type, int flags, int nodelete) (Elf_Phdr *)((char *)libaddr + ehdr->e_phoff), ehdr->e_phnum,type, libaddr, loff); if (object) { - char *soname = (char *)object->Dyn.info[DT_SONAME]; - object->load_size = maxva - minva; /*XXX*/ object->load_list = load_list; /* set inode, dev from stat info */ @@ -339,17 +355,10 @@ _dl_tryload_shlib(const char *libname, int type, int flags, int nodelete) object->nodelete = nodelete; object->relro_addr = relro_addr; object->relro_size = relro_size; + object->islibc = libc; _dl_set_sod(object->load_name, &object->sod); if (ptls != NULL && ptls->p_memsz) _dl_set_tls(object, ptls, libaddr, libname); - - /* Request permission for system calls in libc.so's text segment */ - if (soname != NULL && !_dl_traceld && - _dl_strncmp(soname, "libc.so.", 8) == 0) { - if (_dl_msyscall(exec_start, exec_size) == -1) - _dl_printf("msyscall %lx %lx error\n", - exec_start, exec_size); - } _dl_bcopy(&mut, &object->mut, sizeof mut); _dl_bcopy(&imut, &object->imut, sizeof imut); } else { diff --git a/libexec/ld.so/library_mquery.c b/libexec/ld.so/library_mquery.c index 74070a86a..7e85a5c0f 100644 --- a/libexec/ld.so/library_mquery.c +++ b/libexec/ld.so/library_mquery.c @@ -1,4 +1,4 @@ -/* $OpenBSD: library_mquery.c,v 1.73 2023/12/19 16:13:22 deraadt Exp $ */ +/* $OpenBSD: library_mquery.c,v 1.74 2024/01/16 19:07:31 deraadt Exp $ */ /* * Copyright (c) 2002 Dale Rahn @@ -102,15 +102,15 @@ elf_object_t * _dl_tryload_shlib(const char *libname, int type, int flags, int nodelete) { struct range_vector imut, mut; - int libfile, i; + int libfile, libc = -1, i; struct load_list *ld, *lowld = NULL; elf_object_t *object; Elf_Dyn *dynp = NULL; Elf_Ehdr *ehdr; - Elf_Phdr *phdp; + Elf_Phdr *phdp, *ptls = NULL; + Elf_Phdr *syscall_phdp = NULL; Elf_Addr load_end = 0; Elf_Addr align = _dl_pagesz - 1, off, size; - Elf_Phdr *ptls = NULL; Elf_Addr relro_addr = 0, relro_size = 0; struct stat sb; char hbuf[4096], *exec_start; @@ -325,9 +325,28 @@ retry: _dl_push_range_size(&mut, phdp->p_vaddr + LOFF, phdp->p_memsz); break; + case PT_OPENBSD_SYSCALLS: + syscall_phdp = phdp; + break; } } + libc = _dl_islibc(dynp, LOFF); + if (libc) { + if (syscall_phdp) + _dl_pin(libfile, syscall_phdp, lowld->start, + (size_t)((exec_start + exec_size) - LOFF), + exec_start, exec_size); + + /* + * XXX msyscall() can be removed once pinsyscalls() + * is fully operational + */ + /* Request permission for system calls in libc.so's text segment */ + if (_dl_msyscall(exec_start, exec_size) == -1) + _dl_printf("msyscall %lx %lx error\n", + exec_start, exec_size); + } _dl_close(libfile); dynp = (Elf_Dyn *)((unsigned long)dynp + LOFF); @@ -335,8 +354,6 @@ retry: (Elf_Phdr *)((char *)lowld->start + ehdr->e_phoff), ehdr->e_phnum, type, (Elf_Addr)lowld->start, LOFF); if (object) { - char *soname = (char *)object->Dyn.info[DT_SONAME]; - object->load_size = (Elf_Addr)load_end - (Elf_Addr)lowld->start; object->load_list = lowld; /* set inode, dev from stat info */ @@ -346,18 +363,11 @@ retry: object->nodelete = nodelete; object->relro_addr = relro_addr; object->relro_size = relro_size; + object->islibc = libc; _dl_set_sod(object->load_name, &object->sod); if (ptls != NULL && ptls->p_memsz) _dl_set_tls(object, ptls, (Elf_Addr)lowld->start, libname); - - /* Request permission for system calls in libc.so's text segment */ - if (soname != NULL && !_dl_traceld && - _dl_strncmp(soname, "libc.so.", 8) == 0) { - if (_dl_msyscall(exec_start, exec_size) == -1) - _dl_printf("msyscall %lx %lx error\n", - exec_start, exec_size); - } _dl_bcopy(&mut, &object->mut, sizeof mut); _dl_bcopy(&imut, &object->imut, sizeof imut); } else { diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c index de53dc85d..07cd0d8e1 100644 --- a/libexec/ld.so/loader.c +++ b/libexec/ld.so/loader.c @@ -1,4 +1,4 @@ -/* $OpenBSD: loader.c,v 1.219 2024/01/14 09:39:03 kettenis Exp $ */ +/* $OpenBSD: loader.c,v 1.220 2024/01/16 19:07:31 deraadt Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -440,11 +440,14 @@ _dl_load_dep_libs(elf_object_t *object, int flags, int booting) _dl_cache_grpsym_list_setup(object); + /* + * XXX pinsyscall(SYS_execve,...) can be removed once pinsyscalls() + * is fully operational + */ for (obj = _dl_objects; booting && obj != NULL; obj = obj->next) { - char *soname = (char *)obj->Dyn.info[DT_SONAME]; struct sym_res sr; - if (!soname || _dl_strncmp(soname, "libc.so.", 8)) + if (!obj->islibc) continue; sr = _dl_find_symbol("execve", SYM_SEARCH_SELF|SYM_PLT|SYM_WARNNOTFOUND, NULL, obj); diff --git a/libexec/ld.so/resolve.c b/libexec/ld.so/resolve.c index 191634115..b6e21f9d0 100644 --- a/libexec/ld.so/resolve.c +++ b/libexec/ld.so/resolve.c @@ -1,4 +1,4 @@ -/* $OpenBSD: resolve.c,v 1.100 2023/07/08 14:09:43 jasper Exp $ */ +/* $OpenBSD: resolve.c,v 1.101 2024/01/16 19:07:31 deraadt Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -29,6 +29,8 @@ #define _DYN_LOADER #include +#include +#include #include #include @@ -36,6 +38,7 @@ #include "util.h" #include "path.h" #include "resolve.h" +#include "syscall.h" /* substitution types */ typedef enum { @@ -745,3 +748,82 @@ _dl_debug_state(void) { /* Debugger stub */ } + +/* + * Search for DT_SONAME, and check if this is libc + */ +int +_dl_islibc(Elf_Dyn *_dynp, Elf_Addr loff) +{ + Elf_Dyn *d, *dynp = (Elf_Dyn *)((unsigned long)_dynp + loff); + long base = 0; + + for (d = dynp; d->d_tag != DT_NULL; d++) + if (d->d_tag == DT_STRTAB) { + base = d->d_un.d_ptr + loff; + break; + } + if (base == 0) + return 0; + for (d = dynp; d->d_tag != DT_NULL; d++) + if (d->d_tag == DT_SONAME) { + if (_dl_strncmp((char *)(base + d->d_un.d_ptr), + "libc.so.", 8) == 0) + return 1; + break; + } + return 0; +} + +void +_dl_pin(int file, Elf_Phdr *phdp, void *base, size_t len, + void *exec_base, size_t exec_size) +{ + struct pinsyscalls { + u_int offset; + u_int sysno; + } *syscalls; + int npins = 0, nsyscalls, i; + u_int *pins = NULL; + vaddr_t offset; + + if (phdp->p_filesz > SYS_MAXSYSCALL * 2 * sizeof(*syscalls) || + phdp->p_filesz % sizeof(*syscalls) != 0 || + phdp->p_offset & 0x3) + return; + syscalls = _dl_mmap(NULL, phdp->p_filesz, PROT_READ, + MAP_PRIVATE|MAP_FILE, file, phdp->p_offset); + if (syscalls == MAP_FAILED) + return; + + /* Validate, and calculate pintable size */ + nsyscalls = phdp->p_filesz / sizeof(*syscalls); + for (i = 0; i < nsyscalls; i++) { + if (syscalls[i].sysno < 0 || + syscalls[i].sysno >= SYS_MAXSYSCALL || + syscalls[i].offset >= len) + goto bad; + npins = MAXIMUM(npins, syscalls[i].sysno); + } + npins++; + + /* + * Fill pintable: 0 = invalid, -1 = accept, else offset + * from base, rebase to text_start while at it + */ + pins = _dl_calloc(npins, sizeof(u_int)); + offset = exec_base - base; + for (i = 0; i < nsyscalls; i++) { + if (pins[syscalls[i].sysno]) + pins[syscalls[i].sysno] = (u_int)-1; /* duplicated */ + else + pins[syscalls[i].sysno] = syscalls[i].offset - offset; + } + base += offset; + len = len - offset; +bad: + _dl_munmap(syscalls, phdp->p_filesz); + if (pins) + _dl_pinsyscalls(base, len, pins, npins); + _dl_free(pins); +} diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h index 8f3411dcf..0b3278e6f 100644 --- a/libexec/ld.so/resolve.h +++ b/libexec/ld.so/resolve.h @@ -1,4 +1,4 @@ -/* $OpenBSD: resolve.h,v 1.106 2023/12/19 16:13:22 deraadt Exp $ */ +/* $OpenBSD: resolve.h,v 1.107 2024/01/16 19:07:31 deraadt Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -245,6 +245,7 @@ struct elf_object { struct range_vector imut; struct range_vector mut; + int islibc; }; struct dep_node { @@ -340,6 +341,9 @@ typedef void lock_cb(int); void _dl_thread_kern_go(lock_cb *); lock_cb *_dl_thread_kern_stop(void); +int _dl_islibc(Elf_Dyn *_dynp, Elf_Addr loff); +void _dl_pin(int, Elf_Phdr *, void *, size_t, void *, size_t); + char *_dl_getenv(const char *, char **) __boot; void _dl_unsetenv(const char *, char **) __boot; diff --git a/regress/sys/net/pf_table/Makefile b/regress/sys/net/pf_table/Makefile index d4c6d386c..ae87b7818 100644 --- a/regress/sys/net/pf_table/Makefile +++ b/regress/sys/net/pf_table/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.5 2023/08/13 21:21:53 sashan Exp $ +# $OpenBSD: Makefile,v 1.6 2024/01/16 06:40:07 anton Exp $ REGRESS_TARGETS= hit miss cleanup flags CLEANFILES= stamp-* \ @@ -58,31 +58,31 @@ pf-reftab.conf: # exists before pf-instab.conf gets loaded. # table-pgone.out: - @echo '--a-r-- instance regress/ttest' > $@ - @echo '----r-- reference regress/ttest' >> $@ + @echo '--a-r-- instance@regress/ttest' > $@ + @echo '----r-- reference@regress/ttest' >> $@ # # verify table got persistent flag after we # run 'pfctl -t instance -T add ...' # table-persist.out: - @echo '-pa-r-- instance regress/ttest' > $@ - @echo '----r-- reference regress/ttest' >> $@ + @echo '-pa-r-- instance@regress/ttest' > $@ + @echo '----r-- reference@regress/ttest' >> $@ # # verify tables and are created on behalf of # reference by rule after pf-reftab.conf got loaded. # table-ref.out: - @echo '----r-- instance regress/ttest' > $@ - @echo '----r-- reference regress/ttest' >> $@ + @echo '----r-- instance@regress/ttest' > $@ + @echo '----r-- reference@regress/ttest' >> $@ # # verify reference to table (persistent) is gone # after rules got flushed # table-refgone.out: - @echo '-pa---- instance regress/ttest' > $@ + @echo '-pa---- instance@regress/ttest' > $@ flags: pf-instab.conf pf-reftab.conf table-pgone.out table-persist.out \ table-ref.out table-refgone.out diff --git a/sys/dev/pci/if_iwmreg.h b/sys/dev/pci/if_iwmreg.h index ea05c7b2b..15d471e88 100644 --- a/sys/dev/pci/if_iwmreg.h +++ b/sys/dev/pci/if_iwmreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwmreg.h,v 1.68 2022/03/19 10:26:52 stsp Exp $ */ +/* $OpenBSD: if_iwmreg.h,v 1.69 2024/01/16 12:21:02 kevlo Exp $ */ /****************************************************************************** * @@ -3361,7 +3361,7 @@ struct iwm_rx_mpdu_desc_v1 { uint32_t phy_data0; uint32_t phy_data1; }; - }; + } __packed; } __packed; #define IWM_RX_REORDER_DATA_INVALID_BAID 0x7f diff --git a/sys/kern/exec_elf.c b/sys/kern/exec_elf.c index 4721cfd09..16b66d5e6 100644 --- a/sys/kern/exec_elf.c +++ b/sys/kern/exec_elf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: exec_elf.c,v 1.183 2023/07/12 19:34:14 jasper Exp $ */ +/* $OpenBSD: exec_elf.c,v 1.184 2024/01/16 19:05:01 deraadt Exp $ */ /* * Copyright (c) 1996 Per Fogelstrom @@ -81,6 +81,7 @@ #include #include #include +#include #include @@ -97,6 +98,8 @@ 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)) @@ -265,6 +268,74 @@ elf_read_from(struct proc *p, struct vnode *vp, u_long off, void *buf, 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. @@ -276,7 +347,7 @@ elf_load_file(struct proc *p, char *path, struct exec_package *epp, int error, i; struct nameidata nd; Elf_Ehdr eh; - Elf_Phdr *ph = NULL; + Elf_Phdr *ph = NULL, *syscall_ph = NULL; u_long phsize = 0; Elf_Addr addr; struct vnode *vp; @@ -290,6 +361,7 @@ elf_load_file(struct proc *p, char *path, struct exec_package *epp, 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; @@ -432,6 +504,12 @@ elf_load_file(struct proc *p, char *path, struct exec_package *epp, 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; @@ -461,12 +539,34 @@ elf_load_file(struct proc *p, char *path, struct exec_package *epp, 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: @@ -491,8 +591,8 @@ int exec_elf_makecmds(struct proc *p, struct exec_package *epp) { Elf_Ehdr *eh = epp->ep_hdr; - Elf_Phdr *ph, *pp, *base_ph = NULL; - Elf_Addr phdr = 0, exe_base = 0; + 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; @@ -633,11 +733,13 @@ exec_elf_makecmds(struct proc *p, struct exec_package *epp) /* * Permit system calls in main-text static binaries. - * Also block the ld.so syscall-grant + * static binaries may not call msyscall() or + * pinsyscalls() */ if (interp == NULL) { syscall = VMCMD_SYSCALL; p->p_vmspace->vm_map.flags |= VM_MAP_SYSCALL_ONCE; + p->p_vmspace->vm_map.flags |= VM_MAP_PINSYSCALL_ONCE; } /* @@ -696,6 +798,9 @@ exec_elf_makecmds(struct proc *p, struct exec_package *epp) epp->ep_tsize = addr+size - epp->ep_taddr; } + if (interp == NULL) + exe_end = epp->ep_taddr + + epp->ep_tsize; /* end of TEXT */ } break; @@ -735,7 +840,10 @@ exec_elf_makecmds(struct proc *p, struct exec_package *epp) 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 @@ -745,6 +853,25 @@ exec_elf_makecmds(struct proc *p, struct exec_package *epp) } } + 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; /* diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 9d8ec9813..47048040c 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_exec.c,v 1.252 2023/10/30 07:13:10 claudio Exp $ */ +/* $OpenBSD: kern_exec.c,v 1.253 2024/01/16 19:05:01 deraadt Exp $ */ /* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */ /*- @@ -314,6 +314,8 @@ sys_execve(struct proc *p, void *v, register_t *retval) 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) { @@ -514,6 +516,30 @@ sys_execve(struct proc *p, void *v, register_t *retval) 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 */ @@ -752,6 +778,7 @@ bad: 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); diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 06aabdc07..8221cff38 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_exit.c,v 1.218 2024/01/15 15:47:37 mvs Exp $ */ +/* $OpenBSD: kern_exit.c,v 1.219 2024/01/16 19:05:01 deraadt Exp $ */ /* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */ /* @@ -217,6 +217,11 @@ exit1(struct proc *p, int xexit, int xsig, int flags) 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. diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index c606826af..40a2e54f4 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_fork.c,v 1.254 2024/01/15 15:47:37 mvs Exp $ */ +/* $OpenBSD: kern_fork.c,v 1.255 2024/01/16 19:05:01 deraadt Exp $ */ /* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */ /* @@ -249,6 +249,21 @@ process_new(struct proc *p, struct process *parent, int flags) 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. diff --git a/sys/sys/exec.h b/sys/sys/exec.h index 0fb89f402..aa23b4c5e 100644 --- a/sys/sys/exec.h +++ b/sys/sys/exec.h @@ -1,4 +1,4 @@ -/* $OpenBSD: exec.h,v 1.52 2023/04/19 15:37:36 kettenis Exp $ */ +/* $OpenBSD: exec.h,v 1.53 2024/01/16 19:05:00 deraadt Exp $ */ /* $NetBSD: exec.h,v 1.59 1996/02/09 18:25:09 christos Exp $ */ /*- @@ -131,6 +131,9 @@ struct exec_package { struct elf_args *ep_args; /* ELF info */ void *ep_auxinfo; /* userspace auxinfo address */ char *ep_interp; /* name of interpreter if any */ + vaddr_t ep_pinstart, ep_pinend; /* executable region */ + u_int *ep_pins; /* array of system call offsets */ + int ep_npins; /* entries in array */ }; #define EXEC_INDIR 0x0001 /* script handling already done */ #define EXEC_HASFD 0x0002 /* holding a shell script */ diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 31ca608e5..66e77a51a 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.h,v 1.353 2024/01/15 15:47:37 mvs Exp $ */ +/* $OpenBSD: proc.h,v 1.354 2024/01/16 19:05:00 deraadt Exp $ */ /* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */ /*- @@ -118,6 +118,13 @@ 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 @@ -242,6 +249,9 @@ struct process { /* 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; /* Number of threads. */ @@ -285,6 +295,8 @@ struct process { #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" \ diff --git a/sys/sys/syscall_mi.h b/sys/sys/syscall_mi.h index b9cf7bc07..9bdb3e674 100644 --- a/sys/sys/syscall_mi.h +++ b/sys/sys/syscall_mi.h @@ -1,4 +1,4 @@ -/* $OpenBSD: syscall_mi.h,v 1.29 2023/12/12 15:30:55 deraadt Exp $ */ +/* $OpenBSD: syscall_mi.h,v 1.30 2024/01/16 19:05:00 deraadt Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -33,8 +33,11 @@ #include #include +#include +#include #include #include +#include #include #ifdef KTRACE @@ -46,6 +49,79 @@ #include #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; + } + 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; + } + if (error == 0) + return (0); +#ifdef KTRACE + if (KTRPOINT(p, KTR_PINSYSCALL)) + ktrpinsyscall(p, error, code, addr); +#endif + KERNEL_LOCK(); + 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. @@ -91,6 +167,9 @@ mi_syscall(struct proc *p, register_t code, const struct sysent *callp, uvm_map_inentry_pc, p->p_vmspace->vm_map.wserial)) 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(); diff --git a/sys/uvm/uvm_map.c b/sys/uvm/uvm_map.c index 11322f099..786a7d690 100644 --- a/sys/uvm/uvm_map.c +++ b/sys/uvm/uvm_map.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_map.c,v 1.319 2023/08/02 09:19:47 mpi Exp $ */ +/* $OpenBSD: uvm_map.c,v 1.320 2024/01/16 19:05:01 deraadt Exp $ */ /* $NetBSD: uvm_map.c,v 1.86 2000/11/27 08:40:03 chs Exp $ */ /* @@ -3407,7 +3407,8 @@ uvmspace_exec(struct proc *p, vaddr_t start, vaddr_t end) * when a process execs another program image. */ vm_map_lock(map); - vm_map_modflags(map, 0, VM_MAP_WIREFUTURE|VM_MAP_SYSCALL_ONCE); + vm_map_modflags(map, 0, VM_MAP_WIREFUTURE | + VM_MAP_SYSCALL_ONCE | VM_MAP_PINSYSCALL_ONCE); /* * now unmap the old program @@ -3944,7 +3945,8 @@ uvmspace_fork(struct process *pr) new_map, new_entry->start, new_entry->end); } } - new_map->flags |= old_map->flags & VM_MAP_SYSCALL_ONCE; + new_map->flags |= old_map->flags & + (VM_MAP_SYSCALL_ONCE | VM_MAP_PINSYSCALL_ONCE); #ifdef PMAP_CHECK_COPYIN if (PMAP_CHECK_COPYIN) { memcpy(&new_map->check_copyin, &old_map->check_copyin, diff --git a/sys/uvm/uvm_map.h b/sys/uvm/uvm_map.h index a0a3dc002..5b5884702 100644 --- a/sys/uvm/uvm_map.h +++ b/sys/uvm/uvm_map.h @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_map.h,v 1.87 2023/08/02 09:19:47 mpi Exp $ */ +/* $OpenBSD: uvm_map.h,v 1.88 2024/01/16 19:05:01 deraadt Exp $ */ /* $NetBSD: uvm_map.h,v 1.24 2001/02/18 21:19:08 chs Exp $ */ /* @@ -329,6 +329,7 @@ struct vm_map { #define VM_MAP_GUARDPAGES 0x20 /* rw: add guard pgs to map */ #define VM_MAP_ISVMSPACE 0x40 /* ro: map is a vmspace */ #define VM_MAP_SYSCALL_ONCE 0x80 /* rw: libc syscall registered */ +#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. */ diff --git a/sys/uvm/uvm_mmap.c b/sys/uvm/uvm_mmap.c index 1ff2d3106..bccfcc10d 100644 --- a/sys/uvm/uvm_mmap.c +++ b/sys/uvm/uvm_mmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_mmap.c,v 1.183 2023/12/07 13:59:05 deraadt Exp $ */ +/* $OpenBSD: uvm_mmap.c,v 1.184 2024/01/16 19:05:01 deraadt Exp $ */ /* $NetBSD: uvm_mmap.c,v 1.49 2001/02/18 21:19:08 chs Exp $ */ /* @@ -644,13 +644,65 @@ sys_pinsyscall(struct proc *p, void *v, register_t *retval) return (0); } - /* - * sys_pinsyscalls +/* + * 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) { - /* STUB until other parts are ready */ + 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; + 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. */ + + /* 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; return (0); } diff --git a/usr.bin/file/file.c b/usr.bin/file/file.c index 3183adb48..9fb35dba3 100644 --- a/usr.bin/file/file.c +++ b/usr.bin/file/file.c @@ -1,4 +1,4 @@ -/* $OpenBSD: file.c,v 1.69 2019/11/30 14:01:45 mestre Exp $ */ +/* $OpenBSD: file.c,v 1.70 2024/01/16 13:07:29 claudio Exp $ */ /* * Copyright (c) 2015 Nicholas Marriott @@ -418,12 +418,12 @@ child(int fd, pid_t parent, int argc, char **argv) inf.msg = msg; inf.path = argv[idx]; - inf.fd = imsg.fd; + inf.fd = imsg_get_fd(&imsg); test_file(&inf, width); - if (imsg.fd != -1) - close(imsg.fd); + if (inf.fd != -1) + close(inf.fd); imsg_free(&imsg); ack.idx = idx; diff --git a/usr.bin/tmux/proc.c b/usr.bin/tmux/proc.c index b82a6058e..f0c7e547c 100644 --- a/usr.bin/tmux/proc.c +++ b/usr.bin/tmux/proc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.c,v 1.22 2022/05/30 12:48:57 nicm Exp $ */ +/* $OpenBSD: proc.c,v 1.23 2024/01/16 13:09:11 claudio Exp $ */ /* * Copyright (c) 2015 Nicholas Marriott @@ -92,8 +92,9 @@ proc_event_cb(__unused int fd, short events, void *arg) log_debug("peer %p message %d", peer, imsg.hdr.type); if (peer_check_version(peer, &imsg) != 0) { - if (imsg.fd != -1) - close(imsg.fd); + int fd = imsg_get_fd(&imsg); + if (fd != -1) + close(fd); imsg_free(&imsg); break; } diff --git a/usr.bin/tmux/server-client.c b/usr.bin/tmux/server-client.c index e94bd708f..01e3bd1ac 100644 --- a/usr.bin/tmux/server-client.c +++ b/usr.bin/tmux/server-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server-client.c,v 1.403 2023/12/27 20:23:59 nicm Exp $ */ +/* $OpenBSD: server-client.c,v 1.404 2024/01/16 13:09:11 claudio Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -3002,14 +3002,14 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg) case MSG_IDENTIFY_STDIN: if (datalen != 0) fatalx("bad MSG_IDENTIFY_STDIN size"); - c->fd = imsg->fd; - log_debug("client %p IDENTIFY_STDIN %d", c, imsg->fd); + c->fd = imsg_get_fd(imsg); + log_debug("client %p IDENTIFY_STDIN %d", c, c->fd); break; case MSG_IDENTIFY_STDOUT: if (datalen != 0) fatalx("bad MSG_IDENTIFY_STDOUT size"); - c->out_fd = imsg->fd; - log_debug("client %p IDENTIFY_STDOUT %d", c, imsg->fd); + c->out_fd = imsg_get_fd(imsg); + log_debug("client %p IDENTIFY_STDOUT %d", c, c->out_fd); break; case MSG_IDENTIFY_ENVIRON: if (datalen == 0 || data[datalen - 1] != '\0') diff --git a/usr.sbin/bgpd/logmsg.c b/usr.sbin/bgpd/logmsg.c index 5bee804e7..dfa89f239 100644 --- a/usr.sbin/bgpd/logmsg.c +++ b/usr.sbin/bgpd/logmsg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: logmsg.c,v 1.10 2023/10/14 09:46:14 claudio Exp $ */ +/* $OpenBSD: logmsg.c,v 1.11 2024/01/16 13:15:31 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -133,7 +133,7 @@ log_statechange(struct peer *peer, enum session_state nstate, void log_notification(const struct peer *peer, uint8_t errcode, uint8_t subcode, - u_char *data, uint16_t datalen, const char *dir) + struct ibuf *data, const char *dir) { char *p; const char *suberrname = NULL; diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c index 93e7ba421..d3f41d92e 100644 --- a/usr.sbin/bgpd/session.c +++ b/usr.sbin/bgpd/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.459 2024/01/12 11:19:51 claudio Exp $ */ +/* $OpenBSD: session.c,v 1.460 2024/01/16 13:15:31 claudio Exp $ */ /* * Copyright (c) 2003, 2004, 2005 Henning Brauer @@ -74,8 +74,9 @@ int session_sendmsg(struct bgp_msg *, struct peer *); void session_open(struct peer *); void session_keepalive(struct peer *); void session_update(uint32_t, void *, size_t); -void session_notification(struct peer *, uint8_t, uint8_t, void *, - ssize_t); +void session_notification(struct peer *, uint8_t, uint8_t, struct ibuf *); +void session_notification_data(struct peer *, uint8_t, uint8_t, void *, + size_t); void session_rrefresh(struct peer *, uint8_t, uint8_t); int session_graceful_restart(struct peer *); int session_graceful_stop(struct peer *); @@ -706,7 +707,7 @@ bgp_fsm(struct peer *peer, enum session_events event) case EVNT_TIMER_HOLDTIME: case EVNT_TIMER_SENDHOLD: session_notification(peer, ERR_HOLDTIMEREXPIRED, - 0, NULL, 0); + 0, NULL); change_state(peer, STATE_IDLE, event); break; case EVNT_RCVD_OPEN: @@ -727,7 +728,7 @@ bgp_fsm(struct peer *peer, enum session_events event) break; default: session_notification(peer, - ERR_FSM, ERR_FSM_UNEX_OPENSENT, NULL, 0); + ERR_FSM, ERR_FSM_UNEX_OPENSENT, NULL); change_state(peer, STATE_IDLE, event); break; } @@ -747,7 +748,7 @@ bgp_fsm(struct peer *peer, enum session_events event) case EVNT_TIMER_HOLDTIME: case EVNT_TIMER_SENDHOLD: session_notification(peer, ERR_HOLDTIMEREXPIRED, - 0, NULL, 0); + 0, NULL); change_state(peer, STATE_IDLE, event); break; case EVNT_TIMER_KEEPALIVE: @@ -763,7 +764,7 @@ bgp_fsm(struct peer *peer, enum session_events event) break; default: session_notification(peer, - ERR_FSM, ERR_FSM_UNEX_OPENCONFIRM, NULL, 0); + ERR_FSM, ERR_FSM_UNEX_OPENCONFIRM, NULL); change_state(peer, STATE_IDLE, event); break; } @@ -783,7 +784,7 @@ bgp_fsm(struct peer *peer, enum session_events event) case EVNT_TIMER_HOLDTIME: case EVNT_TIMER_SENDHOLD: session_notification(peer, ERR_HOLDTIMEREXPIRED, - 0, NULL, 0); + 0, NULL); change_state(peer, STATE_IDLE, event); break; case EVNT_TIMER_KEEPALIVE: @@ -805,7 +806,7 @@ bgp_fsm(struct peer *peer, enum session_events event) break; default: session_notification(peer, - ERR_FSM, ERR_FSM_UNEX_ESTABLISHED, NULL, 0); + ERR_FSM, ERR_FSM_UNEX_ESTABLISHED, NULL); change_state(peer, STATE_IDLE, event); break; } @@ -1673,23 +1674,39 @@ session_update(uint32_t peerid, void *data, size_t datalen) p->stats.msg_sent_update++; } +void +session_notification_data(struct peer *p, uint8_t errcode, uint8_t subcode, + void *data, size_t datalen) +{ + struct ibuf ibuf; + + ibuf_from_buffer(&ibuf, data, datalen); + session_notification(p, errcode, subcode, &ibuf); +} + void session_notification(struct peer *p, uint8_t errcode, uint8_t subcode, - void *data, ssize_t datalen) + struct ibuf *ibuf) { struct bgp_msg *buf; int errs = 0; + size_t datalen = 0; if (p->stats.last_sent_errcode) /* some notification already sent */ return; - log_notification(p, errcode, subcode, data, datalen, "sending"); + log_notification(p, errcode, subcode, ibuf, "sending"); /* cap to maximum size */ - if (datalen > MAX_PKTSIZE - MSGSIZE_NOTIFICATION_MIN) { - log_peer_warnx(&p->conf, - "oversized notification, data trunkated"); - datalen = MAX_PKTSIZE - MSGSIZE_NOTIFICATION_MIN; + if (ibuf != NULL) { + if (ibuf_size(ibuf) > + MAX_PKTSIZE - MSGSIZE_NOTIFICATION_MIN) { + log_peer_warnx(&p->conf, + "oversized notification, data trunkated"); + ibuf_truncate(ibuf, MAX_PKTSIZE - + MSGSIZE_NOTIFICATION_MIN); + } + datalen = ibuf_size(ibuf); } if ((buf = session_newmsg(NOTIFICATION, @@ -1701,8 +1718,8 @@ session_notification(struct peer *p, uint8_t errcode, uint8_t subcode, errs += ibuf_add_n8(buf->buf, errcode); errs += ibuf_add_n8(buf->buf, subcode); - if (datalen > 0) - errs += ibuf_add(buf->buf, data, datalen); + if (ibuf != NULL) + errs += ibuf_add_buf(buf->buf, ibuf); if (errs) { ibuf_free(buf->buf); @@ -1998,7 +2015,7 @@ session_process_msg(struct peer *p) p->stats.msg_rcvd_rrefresh++; break; default: /* cannot happen */ - session_notification(p, ERR_HEADER, ERR_HDR_TYPE, + session_notification_data(p, ERR_HEADER, ERR_HDR_TYPE, &msgtype, 1); log_warnx("received message with unknown type %u", msgtype); @@ -2034,7 +2051,7 @@ parse_header(struct peer *peer, u_char *data, uint16_t *len, uint8_t *type) p = data; if (memcmp(p, marker, sizeof(marker))) { log_peer_warnx(&peer->conf, "sync error"); - session_notification(peer, ERR_HEADER, ERR_HDR_SYNC, NULL, 0); + session_notification(peer, ERR_HEADER, ERR_HDR_SYNC, NULL); bgp_fsm(peer, EVNT_CON_FATAL); return (-1); } @@ -2048,7 +2065,7 @@ parse_header(struct peer *peer, u_char *data, uint16_t *len, uint8_t *type) if (*len < MSGSIZE_HEADER || *len > MAX_PKTSIZE) { log_peer_warnx(&peer->conf, "received message: illegal length: %u byte", *len); - session_notification(peer, ERR_HEADER, ERR_HDR_LEN, + session_notification_data(peer, ERR_HEADER, ERR_HDR_LEN, &olen, sizeof(olen)); bgp_fsm(peer, EVNT_CON_FATAL); return (-1); @@ -2059,7 +2076,7 @@ parse_header(struct peer *peer, u_char *data, uint16_t *len, uint8_t *type) if (*len < MSGSIZE_OPEN_MIN) { log_peer_warnx(&peer->conf, "received OPEN: illegal len: %u byte", *len); - session_notification(peer, ERR_HEADER, ERR_HDR_LEN, + session_notification_data(peer, ERR_HEADER, ERR_HDR_LEN, &olen, sizeof(olen)); bgp_fsm(peer, EVNT_CON_FATAL); return (-1); @@ -2070,7 +2087,7 @@ parse_header(struct peer *peer, u_char *data, uint16_t *len, uint8_t *type) log_peer_warnx(&peer->conf, "received NOTIFICATION: illegal len: %u byte", *len); - session_notification(peer, ERR_HEADER, ERR_HDR_LEN, + session_notification_data(peer, ERR_HEADER, ERR_HDR_LEN, &olen, sizeof(olen)); bgp_fsm(peer, EVNT_CON_FATAL); return (-1); @@ -2080,7 +2097,7 @@ parse_header(struct peer *peer, u_char *data, uint16_t *len, uint8_t *type) if (*len < MSGSIZE_UPDATE_MIN) { log_peer_warnx(&peer->conf, "received UPDATE: illegal len: %u byte", *len); - session_notification(peer, ERR_HEADER, ERR_HDR_LEN, + session_notification_data(peer, ERR_HEADER, ERR_HDR_LEN, &olen, sizeof(olen)); bgp_fsm(peer, EVNT_CON_FATAL); return (-1); @@ -2090,7 +2107,7 @@ parse_header(struct peer *peer, u_char *data, uint16_t *len, uint8_t *type) if (*len != MSGSIZE_KEEPALIVE) { log_peer_warnx(&peer->conf, "received KEEPALIVE: illegal len: %u byte", *len); - session_notification(peer, ERR_HEADER, ERR_HDR_LEN, + session_notification_data(peer, ERR_HEADER, ERR_HDR_LEN, &olen, sizeof(olen)); bgp_fsm(peer, EVNT_CON_FATAL); return (-1); @@ -2100,7 +2117,7 @@ parse_header(struct peer *peer, u_char *data, uint16_t *len, uint8_t *type) if (*len < MSGSIZE_RREFRESH_MIN) { log_peer_warnx(&peer->conf, "received RREFRESH: illegal len: %u byte", *len); - session_notification(peer, ERR_HEADER, ERR_HDR_LEN, + session_notification_data(peer, ERR_HEADER, ERR_HDR_LEN, &olen, sizeof(olen)); bgp_fsm(peer, EVNT_CON_FATAL); return (-1); @@ -2109,7 +2126,7 @@ parse_header(struct peer *peer, u_char *data, uint16_t *len, uint8_t *type) default: log_peer_warnx(&peer->conf, "received msg with unknown type %u", *type); - session_notification(peer, ERR_HEADER, ERR_HDR_TYPE, + session_notification_data(peer, ERR_HEADER, ERR_HDR_TYPE, type, 1); bgp_fsm(peer, EVNT_CON_FATAL); return (-1); @@ -2146,7 +2163,7 @@ parse_open(struct peer *peer) rversion = version - BGP_VERSION; else rversion = BGP_VERSION; - session_notification(peer, ERR_OPEN, ERR_OPEN_VERSION, + session_notification_data(peer, ERR_OPEN, ERR_OPEN_VERSION, &rversion, sizeof(rversion)); change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); return (-1); @@ -2158,8 +2175,7 @@ parse_open(struct peer *peer) if (as == 0) { log_peer_warnx(&peer->conf, "peer requests unacceptable AS %u", as); - session_notification(peer, ERR_OPEN, ERR_OPEN_AS, - NULL, 0); + session_notification(peer, ERR_OPEN, ERR_OPEN_AS, NULL); change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); return (-1); } @@ -2171,8 +2187,7 @@ parse_open(struct peer *peer) if (holdtime && holdtime < peer->conf.min_holdtime) { log_peer_warnx(&peer->conf, "peer requests unacceptable holdtime %u", holdtime); - session_notification(peer, ERR_OPEN, ERR_OPEN_HOLDTIME, - NULL, 0); + session_notification(peer, ERR_OPEN, ERR_OPEN_HOLDTIME, NULL); change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); return (-1); } @@ -2192,8 +2207,7 @@ parse_open(struct peer *peer) if (ntohl(bgpid) == 0) { log_peer_warnx(&peer->conf, "peer BGPID %u unacceptable", ntohl(bgpid)); - session_notification(peer, ERR_OPEN, ERR_OPEN_BGPID, - NULL, 0); + session_notification(peer, ERR_OPEN, ERR_OPEN_BGPID, NULL); change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); return (-1); } @@ -2207,7 +2221,7 @@ parse_open(struct peer *peer) bad_len: log_peer_warnx(&peer->conf, "corrupt OPEN message received: length mismatch"); - session_notification(peer, ERR_OPEN, 0, NULL, 0); + session_notification(peer, ERR_OPEN, 0, NULL); change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); return (-1); } @@ -2259,8 +2273,7 @@ bad_len: case OPT_PARAM_CAPABILITIES: /* RFC 3392 */ if (parse_capabilities(peer, op_val, op_len, &as) == -1) { - session_notification(peer, ERR_OPEN, 0, - NULL, 0); + session_notification(peer, ERR_OPEN, 0, NULL); change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); return (-1); } @@ -2278,7 +2291,7 @@ bad_len: "received OPEN message with unsupported optional " "parameter: type %u", op_type); session_notification(peer, ERR_OPEN, ERR_OPEN_OPT, - NULL, 0); + NULL); change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); /* no punish */ timer_set(&peer->timers, Timer_IdleHold, 0); @@ -2299,7 +2312,7 @@ bad_len: if (peer->conf.remote_as != as) { log_peer_warnx(&peer->conf, "peer sent wrong AS %s", log_as(as)); - session_notification(peer, ERR_OPEN, ERR_OPEN_AS, NULL, 0); + session_notification(peer, ERR_OPEN, ERR_OPEN_AS, NULL); change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); return (-1); } @@ -2308,14 +2321,13 @@ bad_len: if (!peer->conf.ebgp && peer->remote_bgpid == conf->bgpid) { log_peer_warnx(&peer->conf, "peer BGPID %u conflicts with ours", ntohl(bgpid)); - session_notification(peer, ERR_OPEN, ERR_OPEN_BGPID, - NULL, 0); + session_notification(peer, ERR_OPEN, ERR_OPEN_BGPID, NULL); change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); return (-1); } if (capa_neg_calc(peer, &suberr) == -1) { - session_notification(peer, ERR_OPEN, suberr, NULL, 0); + session_notification(peer, ERR_OPEN, suberr, NULL); change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); return (-1); } @@ -2390,7 +2402,7 @@ parse_rrefresh(struct peer *peer) "received RREFRESH: illegal len: %u byte", datalen); datalen = htons(datalen); - session_notification(peer, ERR_HEADER, + session_notification_data(peer, ERR_HEADER, ERR_HDR_LEN, &datalen, sizeof(datalen)); bgp_fsm(peer, EVNT_CON_FATAL); return (-1); @@ -2407,7 +2419,7 @@ parse_rrefresh(struct peer *peer) p = peer->rbuf->rptr; p += MSGSIZE_HEADER; datalen -= MSGSIZE_HEADER; - session_notification(peer, ERR_RREFRESH, + session_notification_data(peer, ERR_RREFRESH, ERR_RR_INV_LEN, p, datalen); bgp_fsm(peer, EVNT_CON_FATAL); return (-1); @@ -2452,6 +2464,7 @@ parse_rrefresh(struct peer *peer) int parse_notification(struct peer *peer) { + struct ibuf ibuf; u_char *p; uint16_t datalen; uint8_t errcode; @@ -2479,7 +2492,10 @@ parse_notification(struct peer *peer) p += sizeof(subcode); datalen -= sizeof(subcode); - log_notification(peer, errcode, subcode, p, datalen, "received"); + /* XXX */ + ibuf_from_buffer(&ibuf, p, datalen); + log_notification(peer, errcode, subcode, &ibuf, "received"); + peer->errcnt++; peer->stats.last_rcvd_errcode = errcode; peer->stats.last_rcvd_suberr = subcode; @@ -2749,7 +2765,7 @@ parse_capabilities(struct peer *peer, u_char *d, uint16_t dlen, uint32_t *as) log_peer_warnx(&peer->conf, "peer requests unacceptable AS %u", *as); session_notification(peer, ERR_OPEN, - ERR_OPEN_AS, NULL, 0); + ERR_OPEN_AS, NULL); change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); return (-1); } @@ -2948,6 +2964,7 @@ void session_dispatch_imsg(struct imsgbuf *imsgbuf, int idx, u_int *listener_cnt) { struct imsg imsg; + struct ibuf ibuf; struct mrt xmrt; struct route_refresh rr; struct mrt *mrt; @@ -2956,7 +2973,6 @@ session_dispatch_imsg(struct imsgbuf *imsgbuf, int idx, u_int *listener_cnt) struct listen_addr *la, *next, nla; struct session_dependon sdon; struct bgpd_config tconf; - u_char *data; uint32_t peerid; int n, fd, depend_ok, restricted; uint16_t t; @@ -3247,24 +3263,18 @@ session_dispatch_imsg(struct imsgbuf *imsgbuf, int idx, u_int *listener_cnt) case IMSG_UPDATE_ERR: if (idx != PFD_PIPE_ROUTE) fatalx("update request not from RDE"); - if (imsg.hdr.len < IMSG_HEADER_SIZE + 2) { + if ((p = getpeerbyid(conf, peerid)) == NULL) { + log_warnx("no such peer: id=%u", peerid); + break; + } + if (imsg_get_ibuf(&imsg, &ibuf) == -1 || + ibuf_get_n8(&ibuf, &errcode) == -1 || + ibuf_get_n8(&ibuf, &subcode) == -1) { log_warnx("RDE sent invalid notification"); break; } - if ((p = getpeerbyid(conf, imsg.hdr.peerid)) == NULL) { - log_warnx("no such peer: id=%u", - imsg.hdr.peerid); - break; - } - data = imsg.data; - errcode = *data++; - subcode = *data++; - if (imsg.hdr.len == IMSG_HEADER_SIZE + 2) - data = NULL; - - session_notification(p, errcode, subcode, - data, imsg.hdr.len - IMSG_HEADER_SIZE - 2); + session_notification(p, errcode, subcode, &ibuf); switch (errcode) { case ERR_CEASE: switch (subcode) { @@ -3637,37 +3647,36 @@ session_demote(struct peer *p, int level) void session_stop(struct peer *peer, uint8_t subcode) { - char data[REASON_LEN]; - size_t datalen; - size_t reason_len; + struct ibuf *ibuf; char *communication; - datalen = 0; communication = peer->conf.reason; + ibuf = ibuf_dynamic(0, REASON_LEN); + if ((subcode == ERR_CEASE_ADMIN_DOWN || - subcode == ERR_CEASE_ADMIN_RESET) - && communication && *communication) { - reason_len = strlen(communication); - if (reason_len > REASON_LEN - 1) { - log_peer_warnx(&peer->conf, - "trying to send overly long shutdown reason"); - } else { - data[0] = reason_len; - datalen = reason_len + sizeof(data[0]); - memcpy(data + 1, communication, reason_len); + subcode == ERR_CEASE_ADMIN_RESET) && + communication != NULL && *communication != '\0' && + ibuf != NULL) { + if (ibuf_add_n8(ibuf, strlen(communication)) == -1 || + ibuf_add(ibuf, communication, strlen(communication))) { + log_peer_warnx(&peer->conf, + "trying to send overly long shutdown reason"); + ibuf_free(ibuf); + ibuf = NULL; } } switch (peer->state) { case STATE_OPENSENT: case STATE_OPENCONFIRM: case STATE_ESTABLISHED: - session_notification(peer, ERR_CEASE, subcode, data, datalen); + session_notification(peer, ERR_CEASE, subcode, ibuf); break; default: /* session not open, no need to send notification */ break; } + ibuf_free(ibuf); bgp_fsm(peer, EVNT_STOP); } diff --git a/usr.sbin/bgpd/session.h b/usr.sbin/bgpd/session.h index 8c677c3d9..13cbd92d7 100644 --- a/usr.sbin/bgpd/session.h +++ b/usr.sbin/bgpd/session.h @@ -1,4 +1,4 @@ -/* $OpenBSD: session.h,v 1.166 2024/01/11 15:46:25 claudio Exp $ */ +/* $OpenBSD: session.h,v 1.167 2024/01/16 13:15:31 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -273,7 +273,7 @@ char *log_fmt_peer(const struct peer_config *); void log_statechange(struct peer *, enum session_state, enum session_events); void log_notification(const struct peer *, uint8_t, uint8_t, - u_char *, uint16_t, const char *); + struct ibuf *, const char *); void log_conn_attempt(const struct peer *, struct sockaddr *, socklen_t); diff --git a/usr.sbin/btrace/bt_parse.y b/usr.sbin/btrace/bt_parse.y index 1eb528013..b378b89a0 100644 --- a/usr.sbin/btrace/bt_parse.y +++ b/usr.sbin/btrace/bt_parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: bt_parse.y,v 1.56 2023/12/20 14:00:17 dv Exp $ */ +/* $OpenBSD: bt_parse.y,v 1.57 2024/01/16 14:35:56 claudio Exp $ */ /* * Copyright (c) 2019-2023 Martin Pieuchot @@ -123,15 +123,15 @@ static int beflag = 0; /* BEGIN/END parsing context flag */ /* Functions and Map operators */ %token F_DELETE F_PRINT %token MFUNC FUNC0 FUNC1 FUNCN OP1 OP2 OP4 MOP0 MOP1 -%token STRING CSTRING +%token STRING CSTRING GVAR LVAR +%token PVAR PNUM %token NUMBER -%type gvar lvar %type beginend %type plist probe pname %type filter %type action stmt stmtblck stmtlist block -%type vargs mentry mpat pargs staticv +%type vargs mentry mpat pargs %type expr term fterm variable factor func %% @@ -158,18 +158,7 @@ pname : STRING ':' STRING ':' STRING { $$ = bp_new($1, $3, $5, 0); } | STRING ':' HZ ':' NUMBER { $$ = bp_new($1, "hz", NULL, $5); } ; -staticv : '$' NUMBER { $$ = get_varg($2); } - | '$' '#' { $$ = get_nargs(); } - ; - -gvar : '@' STRING { $$ = $2; } - | '@' { $$ = UNNAMED_MAP; } - ; - -lvar : '$' STRING { $$ = $2; } - ; - -mentry : gvar '[' vargs ']' { $$ = bm_find($1, $3); } +mentry : GVAR '[' vargs ']' { $$ = bm_find($1, $3); } ; mpat : MOP0 '(' ')' { $$ = ba_new(NULL, $1); } @@ -212,8 +201,8 @@ fterm : fterm '*' factor { $$ = ba_op(B_AT_OP_MULT, $1, $3); } | factor ; -variable: lvar { $$ = bl_find($1); } - | gvar { $$ = bg_find($1); } +variable: LVAR { $$ = bl_find($1); } + | GVAR { $$ = bg_find($1); } | variable '.' NUMBER { $$ = bi_find($1, $3); } ; @@ -222,14 +211,15 @@ factor : '(' expr ')' { $$ = $2; } | NUMBER { $$ = ba_new($1, B_AT_LONG); } | BUILTIN { $$ = ba_new(NULL, $1); } | CSTRING { $$ = ba_new($1, B_AT_STR); } - | staticv + | PVAR + | PNUM | variable | mentry | func ; -func : STR '(' staticv ')' { $$ = ba_new($3, B_AT_FN_STR); } - | STR '(' staticv ',' expr ')' { $$ = ba_op(B_AT_FN_STR, $3, $5); } +func : STR '(' PVAR ')' { $$ = ba_new($3, B_AT_FN_STR); } + | STR '(' PVAR ',' expr ')' { $$ = ba_op(B_AT_FN_STR, $3, $5); } ; vargs : expr @@ -237,7 +227,7 @@ vargs : expr ; pargs : expr - | gvar ',' expr { $$ = ba_append(bg_find($1), $3); } + | GVAR ',' expr { $$ = ba_append(bg_find($1), $3); } ; NL : /* empty */ @@ -245,17 +235,17 @@ NL : /* empty */ ; stmt : ';' NL { $$ = NULL; } - | gvar '=' expr { $$ = bg_store($1, $3); } - | lvar '=' expr { $$ = bl_store($1, $3); } - | gvar '[' vargs ']' '=' mpat { $$ = bm_insert($1, $3, $6); } + | GVAR '=' expr { $$ = bg_store($1, $3); } + | LVAR '=' expr { $$ = bl_store($1, $3); } + | GVAR '[' vargs ']' '=' mpat { $$ = bm_insert($1, $3, $6); } | FUNCN '(' vargs ')' { $$ = bs_new($1, $3, NULL); } | FUNC1 '(' expr ')' { $$ = bs_new($1, $3, NULL); } | MFUNC '(' variable ')' { $$ = bs_new($1, $3, NULL); } | FUNC0 '(' ')' { $$ = bs_new($1, NULL, NULL); } | F_DELETE '(' mentry ')' { $$ = bm_op($1, $3, NULL); } | F_PRINT '(' pargs ')' { $$ = bs_new($1, $3, NULL); } - | gvar '=' OP1 '(' expr ')' { $$ = bh_inc($1, $5, NULL); } - | gvar '=' OP4 '(' expr ',' vargs ')' { $$ = bh_inc($1, $5, $7); } + | GVAR '=' OP1 '(' expr ')' { $$ = bh_inc($1, $5, NULL); } + | GVAR '=' OP4 '(' expr ',' vargs ')' { $$ = bh_inc($1, $5, $7); } ; stmtblck: IF '(' expr ')' block { $$ = bt_new($3, $5); } @@ -285,7 +275,7 @@ get_varg(int index) const char *errstr = NULL; long val; - if (0 < index && index <= nargs) { + if (1 <= index && index <= nargs) { val = (long)strtonum(vargs[index-1], LONG_MIN, LONG_MAX, &errstr); if (errstr == NULL) @@ -777,6 +767,19 @@ lungetc(void) } } +static inline int +allowed_to_end_number(int x) +{ + return (isspace(x) || x == ')' || x == '/' || x == '{' || x == ';' || + x == ']' || x == ',' || x == '='); +} + +static inline int +allowed_in_string(int x) +{ + return (isalnum(x) || x == '_'); +} + int yylex(void) { @@ -872,6 +875,76 @@ again: case ':': case ';': return c; + case '$': + c = lgetc(); + if (c == '#') { + yylval.v.arg = get_nargs(); + return PNUM; + } else if (isdigit(c)) { + do { + *p++ = c; + if (p == ebuf) { + yyerror("line too long"); + return ERROR; + } + } while ((c = lgetc()) != EOF && isdigit(c)); + lungetc(); + *p = '\0'; + if (c == EOF || allowed_to_end_number(c)) { + const char *errstr = NULL; + int num; + + num = strtonum(buf, 1, INT_MAX, &errstr); + if (errstr) { + yyerror("'$%s' is %s", buf, errstr); + return ERROR; + } + + yylval.v.arg = get_varg(num); + return PVAR; + } + } else if (isalpha(c)) { + do { + *p++ = c; + if (p == ebuf) { + yyerror("line too long"); + return ERROR; + } + } while ((c = lgetc()) != EOF && allowed_in_string(c)); + lungetc(); + *p = '\0'; + if ((yylval.v.string = strdup(buf)) == NULL) + err(1, "%s", __func__); + return LVAR; + } + yyerror("'$%s%c' is an invalid variable name", buf, c); + return ERROR; + break; + case '@': + c = lgetc(); + /* check for unnamed map '@' */ + if (isalpha(c)) { + do { + *p++ = c; + if (p == ebuf) { + yyerror("line too long"); + return ERROR; + } + } while ((c = lgetc()) != EOF && allowed_in_string(c)); + lungetc(); + *p = '\0'; + if ((yylval.v.string = strdup(buf)) == NULL) + err(1, "%s", __func__); + return GVAR; + } else if (allowed_to_end_number(c) || c == '[') { + lungetc(); + *p = '\0'; + yylval.v.string = UNNAMED_MAP; + return GVAR; + } + yyerror("'@%s%c' is an invalid variable name", buf, c); + return ERROR; + break; case EOF: return 0; case '"': @@ -915,9 +988,6 @@ again: break; } -#define allowed_to_end_number(x) \ - (isspace(x) || x == ')' || x == '/' || x == '{' || x == ';' || x == ']' || x == ',') - /* parsing number */ if (isdigit(c)) { do { @@ -952,8 +1022,6 @@ again: } } -#define allowed_in_string(x) (isalnum(c) || c == '_') - /* parsing next word */ if (allowed_in_string(c)) { struct keyword *kwp; diff --git a/usr.sbin/rpki-client/rpki-client.8 b/usr.sbin/rpki-client/rpki-client.8 index 8fd47548f..47e56c0af 100644 --- a/usr.sbin/rpki-client/rpki-client.8 +++ b/usr.sbin/rpki-client/rpki-client.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: rpki-client.8,v 1.98 2023/10/13 12:06:49 job Exp $ +.\" $OpenBSD: rpki-client.8,v 1.99 2024/01/16 19:52:39 job Exp $ .\" .\" Copyright (c) 2019 Kristaps Dzonsons .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: October 13 2023 $ +.Dd $Mdocdate: January 16 2024 $ .Dt RPKI-CLIENT 8 .Os .Sh NAME @@ -436,8 +436,8 @@ agreement regarding ARIN service restrictions. .Pp .Rs .%T On the use of the CMS signing-time attribute in RPKI Signed Objects -.%U https://datatracker.ietf.org/doc/html/draft-spaghetti-sidrops-cms-signing-time -.%D June, 2023 +.%U https://datatracker.ietf.org/doc/html/draft-ietf-sidrops-cms-signing-time +.%D Jan, 2024 .Re .Pp .Rs diff --git a/usr.sbin/snmpd/proc.c b/usr.sbin/snmpd/proc.c index 94a78a9a7..941857b71 100644 --- a/usr.sbin/snmpd/proc.c +++ b/usr.sbin/snmpd/proc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.c,v 1.29 2023/12/21 12:43:31 martijn Exp $ */ +/* $OpenBSD: proc.c,v 1.30 2024/01/16 13:33:12 claudio Exp $ */ /* * Copyright (c) 2010 - 2016 Reyk Floeter @@ -644,7 +644,7 @@ proc_dispatch(int fd, short event, void *arg) case IMSG_CTL_PROCFD: IMSG_SIZE_CHECK(&imsg, &pf); memcpy(&pf, imsg.data, sizeof(pf)); - proc_accept(ps, imsg.fd, pf.pf_procid, + proc_accept(ps, imsg_get_fd(&imsg), pf.pf_procid, pf.pf_instance); break; default: @@ -770,14 +770,6 @@ proc_composev(struct privsep *ps, enum privsep_procid id, return (proc_composev_imsg(ps, id, -1, type, -1, -1, iov, iovcnt)); } -int -proc_forward_imsg(struct privsep *ps, struct imsg *imsg, - enum privsep_procid id, int n) -{ - return (proc_compose_imsg(ps, id, n, imsg->hdr.type, - imsg->hdr.peerid, imsg->fd, imsg->data, IMSG_DATA_SIZE(imsg))); -} - struct imsgbuf * proc_ibuf(struct privsep *ps, enum privsep_procid id, int n) { diff --git a/usr.sbin/snmpd/snmpd.h b/usr.sbin/snmpd/snmpd.h index fc0a67a97..00f24c49d 100644 --- a/usr.sbin/snmpd/snmpd.h +++ b/usr.sbin/snmpd/snmpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: snmpd.h,v 1.116 2023/12/21 13:54:05 martijn Exp $ */ +/* $OpenBSD: snmpd.h,v 1.117 2024/01/16 13:33:12 claudio Exp $ */ /* * Copyright (c) 2007, 2008, 2012 Reyk Floeter @@ -506,8 +506,6 @@ int proc_composev_imsg(struct privsep *, enum privsep_procid, int, u_int16_t, u_int32_t, int, const struct iovec *, int); int proc_composev(struct privsep *, enum privsep_procid, uint16_t, const struct iovec *, int); -int proc_forward_imsg(struct privsep *, struct imsg *, - enum privsep_procid, int); struct imsgbuf * proc_ibuf(struct privsep *, enum privsep_procid, int); struct imsgev * diff --git a/usr.sbin/snmpd/snmpe.c b/usr.sbin/snmpd/snmpe.c index 73e25ba32..055d11724 100644 --- a/usr.sbin/snmpd/snmpe.c +++ b/usr.sbin/snmpd/snmpe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: snmpe.c,v 1.93 2023/12/21 12:43:31 martijn Exp $ */ +/* $OpenBSD: snmpe.c,v 1.94 2024/01/16 13:33:13 claudio Exp $ */ /* * Copyright (c) 2007, 2008, 2012 Reyk Floeter @@ -138,7 +138,7 @@ snmpe_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg) { switch (imsg->hdr.type) { case IMSG_AX_FD: - appl_agentx_backend(imsg->fd); + appl_agentx_backend(imsg_get_fd(imsg)); return 0; default: return -1;