Module Name: src Committed By: riastradh Date: Thu Jun 3 09:22:47 UTC 2021
Modified Files: src/sys/kern: kern_ksyms.c Log Message: ksyms(4): Allow multiple concurrent opens of /dev/ksyms. First one takes a snapshot; others all agree with the snapshot. Previously this code path was just broken (could fail horribly if modules were unloaded after one of the opens is closed), so I just blocked it off in an earlier commit, but that broke crash(8). So let's continue allowing multiple opens seeing the same snapshot, but without the horrible bugs. To generate a diff of this commit: cvs rdiff -u -r1.96 -r1.97 src/sys/kern/kern_ksyms.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/kern_ksyms.c diff -u src/sys/kern/kern_ksyms.c:1.96 src/sys/kern/kern_ksyms.c:1.97 --- src/sys/kern/kern_ksyms.c:1.96 Thu Jun 3 01:00:24 2021 +++ src/sys/kern/kern_ksyms.c Thu Jun 3 09:22:47 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_ksyms.c,v 1.96 2021/06/03 01:00:24 riastradh Exp $ */ +/* $NetBSD: kern_ksyms.c,v 1.97 2021/06/03 09:22:47 riastradh Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -73,7 +73,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.96 2021/06/03 01:00:24 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.97 2021/06/03 09:22:47 riastradh Exp $"); #if defined(_KERNEL) && defined(_KERNEL_OPT) #include "opt_copy_symtab.h" @@ -112,7 +112,7 @@ static uint32_t *ksyms_nmap = NULL; #endif static int ksyms_maxlen; -static bool ksyms_isopen; +static uint64_t ksyms_opencnt; static struct ksyms_symtab *ksyms_last_snapshot; static bool ksyms_initted; static bool ksyms_loaded; @@ -791,7 +791,7 @@ ksyms_modunload(const char *name) continue; st->sd_gone = true; ksyms_sizes_calc(); - if (!ksyms_isopen) { + if (ksyms_opencnt == 0) { /* * Ensure ddb never witnesses an inconsistent * state of the queue, unless memory is so @@ -1004,14 +1004,12 @@ ksymsopen(dev_t dev, int oflags, int dev return ENXIO; /* - * Create a "snapshot" of the kernel symbol table. Setting - * ksyms_isopen will prevent symbol tables from being freed. + * Create a "snapshot" of the kernel symbol table. Bumping + * ksyms_opencnt will prevent symbol tables from being freed. */ mutex_enter(&ksyms_lock); - if (ksyms_isopen) { - mutex_exit(&ksyms_lock); - return EBUSY; - } + if (ksyms_opencnt++) + goto out; ksyms_hdr.kh_shdr[SYMTAB].sh_size = ksyms_symsz; ksyms_hdr.kh_shdr[SYMTAB].sh_info = ksyms_symsz / sizeof(Elf_Sym); ksyms_hdr.kh_shdr[STRTAB].sh_offset = ksyms_symsz + @@ -1020,9 +1018,8 @@ ksymsopen(dev_t dev, int oflags, int dev ksyms_hdr.kh_shdr[SHCTF].sh_offset = ksyms_strsz + ksyms_hdr.kh_shdr[STRTAB].sh_offset; ksyms_hdr.kh_shdr[SHCTF].sh_size = ksyms_ctfsz; - ksyms_isopen = true; ksyms_last_snapshot = TAILQ_LAST(&ksyms_symtabs, ksyms_symtab_queue); - mutex_exit(&ksyms_lock); +out: mutex_exit(&ksyms_lock); return 0; } @@ -1036,7 +1033,8 @@ ksymsclose(dev_t dev, int oflags, int de /* Discard references to symbol tables. */ mutex_enter(&ksyms_lock); - ksyms_isopen = false; + if (--ksyms_opencnt) + goto out; ksyms_last_snapshot = NULL; TAILQ_FOREACH_SAFE(st, &ksyms_symtabs, sd_queue, next) { if (st->sd_gone) { @@ -1053,7 +1051,7 @@ ksymsclose(dev_t dev, int oflags, int de } if (!TAILQ_EMPTY(&to_free)) ksyms_sizes_calc(); - mutex_exit(&ksyms_lock); +out: mutex_exit(&ksyms_lock); TAILQ_FOREACH_SAFE(st, &to_free, sd_queue, next) { kmem_free(st->sd_nmap, st->sd_nmapsize * sizeof(uint32_t));