From nobody Mon Jun 29 17:13:21 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gptCP6jxTz6jWbY for ; Mon, 29 Jun 2026 17:13:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gptCP67Qyz3n9q for ; Mon, 29 Jun 2026 17:13:21 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782753201; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=G8kkaHRrfYPrJLAWLgoDclzjCod6TCW4bHs0kch/yaM=; b=Kdtam2ZWcgh1ABE3mCsPbViLk9TfgTSE4ieL94wvd4xWo0HaebnR5R1Ct+p/PNnNCGH6gQ lMjSbxMtSiG+7o/vn5GDtWQAJDJfIw+8mPyPlkXZhgD4kM6IwxUgLZu044I9gZPhRFhPs0 yc9131MTxBxdZLaZMm/GUO3tciVQ00jhmVnffuLU9YJhB7aNPal3xdCH+17s3B/kpr45/7 zcWlBAMHDED+epvDvHD+gOpxu7++gDfbgkK7UWc25wSWChIjRaYZIRcmdu7B68VZkk1b/m dPr147szlMj5pHSP0325391ePH78W0+pkJJaQiWhvRJz5ezbYxEIfHy13L7xfQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1782753201; a=rsa-sha256; cv=none; b=U1XPdah8+E1cfA5RHJtFpTlfwnPfyj6Lxq2wsY5r+YgFabRbQNAzIc0vRUYkBUrSIweeUI 7DVPZ3wV2S9xhjMSjy/P26CDiTg6s0qPFZd8ZK5wn0CoMi+tH+Toaqr0EnK63Cn4AlG/25 ERNsagfe/nlxyUFEmk3wG7BYexhQYZ3gXEqxypTzpDcITispjoyvXSQvV6yytXcpbnsd/x Ka6NcoRNOQ9261k/DQgFLJs4aUVITtzbhEfM+LnKTNmqkeAq5wJPlHitgBbGRFMB672WZ1 NYUg8VhDUdxYEtzCmgZP9WW0MTGCngJzXfdzOjGGBo6gfieUtJ5p9KfcaZEKFw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782753201; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=G8kkaHRrfYPrJLAWLgoDclzjCod6TCW4bHs0kch/yaM=; b=jEdVZTtB29akgJiSTIAeKSDTrh47boXHvQi3iVb9tVh/LZIffbFtyDkDmg3cRuai6OuvP3 8xST70SCd8sYBQEvNxk9QgLPXqdpDSCJjgIdrJKMtbGDiKXDXFBcLI85zKYHH7mmtfqIGA y2JHpUj7BZPqJ+y5LCj+Y6g+5R3OH505Ax3TStL/sg7oNET/iblVIIjL9BPkHjZ0FVHM7O eARK2o4YmrJcoBNZCjhcam+Dt62ngJK+2f2W2dK4mUgW/o290i+IwEFetkFbIs5RBNZQ60 tqsPQNduQh/43HkMFwQaDaIxCf5lfl1VgfEmr8BVhtBK7YGZhELU9ixQHMjACQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gptCP4n2Jz16K5 for ; Mon, 29 Jun 2026 17:13:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 433f9 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 29 Jun 2026 17:13:21 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Ryan Libby Subject: git: 2407abc9fb3b - main - witness: harden tunables for large settings List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: rlibby X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 2407abc9fb3b45d6d734d564706c76aa793b102a Auto-Submitted: auto-generated Date: Mon, 29 Jun 2026 17:13:21 +0000 Message-Id: <6a42a7b1.433f9.488a2de@gitrepo.freebsd.org> The branch main has been updated by rlibby: URL: https://cgit.FreeBSD.org/src/commit/?id=2407abc9fb3b45d6d734d564706c76aa793b102a commit 2407abc9fb3b45d6d734d564706c76aa793b102a Author: Ryan Libby AuthorDate: 2026-06-29 16:54:30 +0000 Commit: Ryan Libby CommitDate: 2026-06-29 16:54:30 +0000 witness: harden tunables for large settings Harden witness against reasonable tunable settings causing boot panics or scribblers. For now, don't bother to harden this completely. Panics are still achievable by setting the tunables to negative or very large values. The recent change to respect the setting of debug.witness.witness_count (08180f1b613b) exposed that there are no guard rails on that setting, setting it to large but plausible values can cause integer overflow or cause attempted use of memory beyond what is actually available. Add some guard rails, fall back to default configuration if the tuned values are too large, and fall back to a minimum memory allocation if even the defaults are too large. Also don't allow witness to use over half of the memory segment, as there are other early allocators after witness too. Reported by: asomers Reviewed by: kib, markj (previous version) Fixes: 08180f1b613b ("witness: actually set read-only tunables in time for witness_startup") Sponsored by: Dell Inc. Differential Revision: https://reviews.freebsd.org/D57793 --- sys/kern/subr_witness.c | 67 ++++++++++++++++++++++++++++++++++++++++++++----- sys/sys/lock.h | 2 +- sys/vm/vm_page.c | 11 ++++++-- 3 files changed, 71 insertions(+), 9 deletions(-) diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c index 21d015c4f381..52f8fa51fd25 100644 --- a/sys/kern/subr_witness.c +++ b/sys/kern/subr_witness.c @@ -419,19 +419,16 @@ static u_long witness_count = WITNESS_COUNT; SYSCTL_ULONG(_debug_witness, OID_AUTO, witness_count, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &witness_count, 0, "Maximum count of lock type entries"); -TUNABLE_ULONG("debug.witness.witness_count", &witness_count); static u_long witness_lo_data_count = WITNESS_LO_DATA_COUNT; SYSCTL_ULONG(_debug_witness, OID_AUTO, lock_order_data_count, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &witness_lo_data_count, 0, "Maximum count of lock order data (stacks) to track"); -TUNABLE_ULONG("debug.witness.lock_order_data_count", &witness_lo_data_count); static u_long witness_lo_hash_size = WITNESS_LO_HASH_SIZE; SYSCTL_ULONG(_debug_witness, OID_AUTO, lock_order_hash_size, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &witness_lo_hash_size, 0, "Hash table size for lock order data"); -TUNABLE_ULONG("debug.witness.lock_order_hash_size", &witness_lo_hash_size); /* * Output channel for witness messages. By default we print to the console. @@ -489,6 +486,7 @@ static struct witness *w_data; static uint8_t **w_rmatrix; static struct lock_list_entry w_locklistdata[LOCK_CHILDCOUNT]; static struct witness_hash w_hash; /* The witness hash table. */ +static u_long w_sz; /* Witness startup memory allocation size */ /* The lock order data hash */ static struct witness_lock_order_data *w_lodata; @@ -791,10 +789,10 @@ fixup_filename(const char *file) /* * Calculate the size of early witness structures. */ -int -witness_startup_count(void) +static u_long +witness_startup_calc(void) { - int sz; + u_long sz; sz = sizeof(struct witness) * witness_count; sz += sizeof(*w_rmatrix) * (witness_count + 1); @@ -803,10 +801,65 @@ witness_startup_count(void) sz += sizeof(void *); sz += sizeof(w_lodata[0]) * witness_lo_data_count; sz += sizeof(w_lohash.wloh_array[0]) * witness_lo_hash_size; + sz = round_page(sz); return (sz); } +u_long +witness_startup_count(u_long avail) +{ + + /* + * Tune witness. We make an effort to protect against misconfiguration + * consuming more memory than available, but we do not robustly protect + * against integer overflow for all possible user-supplied values. + */ + TUNABLE_ULONG_FETCH("debug.witness.witness_count", &witness_count); + witness_count = ulmax(witness_count, 1); + TUNABLE_ULONG_FETCH("debug.witness.lock_order_data_count", + &witness_lo_data_count); + TUNABLE_ULONG_FETCH("debug.witness.lock_order_hash_size", + &witness_lo_hash_size); + w_sz = witness_startup_calc(); + if (bootverbose) + printf("WITNESS configuration requests %lu KiB " + "of startup allocations with witness_count=%lu, " + "lock_order_data_count=%lu, lock_order_hash_size=%lu\n", + w_sz / 1024, witness_count, witness_lo_data_count, + witness_lo_hash_size); + if (w_sz <= avail) + return (w_sz); + + /* Memory allocation would be too large, try fallbacks. */ + printf("WARNING: WITNESS configuration requests %lu KiB, " + "with %lu KiB available\n", w_sz / 1024, avail / 1024); + witness_count = ulmin(witness_count, WITNESS_COUNT); + witness_lo_data_count = ulmin(witness_lo_data_count, + WITNESS_LO_DATA_COUNT); + witness_lo_hash_size = ulmin(witness_lo_hash_size, + WITNESS_LO_HASH_SIZE); + w_sz = witness_startup_calc(); + if (w_sz <= avail) { + printf("WARNING: WITNESS configuration reduced to defaults\n"); + return (w_sz); + } + + /* Minimize startup allocations, functionally disabling witness. */ + witness_count = 1; + witness_lo_data_count = 0; + witness_lo_hash_size = 1; + w_sz = witness_startup_calc(); + if (w_sz <= avail) { + printf("WARNING: WITNESS configuration defaults too large, " + "lock order checks disabled\n"); + return (w_sz); + } + + panic("WITNESS unable to initialize with %lu KiB available", + avail / 1024); +} + /* * The WITNESS-enabled diagnostic code. Note that the witness code does * assume that the early boot is single-threaded at least until after this @@ -843,6 +896,8 @@ witness_startup(void *mem) w_lohash.wloh_array = (void *)p; p += sizeof(w_lohash.wloh_array[0]) * witness_lo_hash_size; + MPASS(p <= (uintptr_t)mem + w_sz); + badstack_sbuf_size = witness_count * 256; /* diff --git a/sys/sys/lock.h b/sys/sys/lock.h index 9d81a49ab52a..74e222176b4a 100644 --- a/sys/sys/lock.h +++ b/sys/sys/lock.h @@ -247,7 +247,7 @@ const char *witness_file(struct lock_object *); void witness_thread_exit(struct thread *); #ifdef WITNESS -int witness_startup_count(void); +u_long witness_startup_count(u_long); void witness_startup(void *); /* Flags for witness_warn(). */ diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 233292bdd6cb..8c953149e6de 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -585,7 +585,7 @@ vm_page_startup(vm_offset_t vaddr) int biggestone, i, segind; #ifdef WITNESS void *mapped; - int witness_size; + u_long witness_size; #endif #if defined(__i386__) && defined(VM_PHYSSEG_DENSE) long ii; @@ -610,7 +610,14 @@ vm_page_startup(vm_offset_t vaddr) new_end = end; #ifdef WITNESS - witness_size = round_page(witness_startup_count()); + /* + * witness(4) support. Allocate and map memory and initialize. + * Advertised available memory is limited in order to avoid witness + * misconfiguration consuming memory needed for subsequent essential + * allocations. + */ + witness_size = round_page(witness_startup_count( + trunc_page((new_end - phys_avail[biggestone]) / 2))); new_end -= witness_size; mapped = pmap_map(&vaddr, new_end, new_end + witness_size, VM_PROT_READ | VM_PROT_WRITE);