From nobody Tue Oct 18 06:03:04 2022 X-Original-To: dev-commits-src-all@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 4Ms3F44KBsz4g7t8; Tue, 18 Oct 2022 06:03:04 +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 "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Ms3F43sWDz3bb2; Tue, 18 Oct 2022 06:03:04 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1666072984; 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=7hNds67efjaeYIRWBy8V6BGm0AnHoFDdn5iwJoGPw+4=; b=dUYm7WxIf1GsJmlLdnuWU6ZucIPE3fMSXsininzn9DG//vzyMYT/rcE0A90D063PYUw9i8 4dzaBm7w0bbChR1btP2WhS5AJCafE1nmlTEis2OaHxhHC47YM+/4ESuAY6P1HWq61r8ZAA OuwnyQOPwIDdy+vsgnpv5CBUc4TVF7GlmOD89/f95CdHGsCo8lRn+y5577vsbiFA0Us/Cy hIb4wF9eLBcAr4Nd1029Nwznjs/FLv+KwuTWzkTkjfHzNu/y1AjleObR3GUZIfLG6/A0EZ rPN9hUzJcvHpYjAP+RQGaYZZygWwztdTxaFUf7qUslMFp42Mx+qXWAL+/aFgMg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (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 did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4Ms3F42wnkz15BK; Tue, 18 Oct 2022 06:03:04 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 29I6348b097255; Tue, 18 Oct 2022 06:03:04 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 29I6340i097254; Tue, 18 Oct 2022 06:03:04 GMT (envelope-from git) Date: Tue, 18 Oct 2022 06:03:04 GMT Message-Id: <202210180603.29I6340i097254@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Colin Percival Subject: git: c32bd97641da - main - kern: Support duplicate variables in early kenv List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: cperciva X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: c32bd97641da2e49188e68fb83452605f6ace0ef Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1666072984; 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=7hNds67efjaeYIRWBy8V6BGm0AnHoFDdn5iwJoGPw+4=; b=R3UZoCNxgkjZ8U/bM17YJXOwpX4DXCU302U6dXShzITvuVo6atl3BBQUAEelADKshYc72t vAmOd7eSVeOPHd2pLyafXa7NOC9JUAFjO35TE9hDouHSVPKQ3i87W5iH9k2uhiX7UBtbPT 6qL5Yy+wmREyBvZpeMJAJqIf0t1zILjSUFEuP8uHXCvCDGODl/HNNr8tLHflLEgzhm00vR FfVOMa6hTC+3gYim/PQfdxjReNFcmgtvhJeUU58heKAIozDmLsJ3u3Sv5S3IzVmKDGviUg xZbw6Z9t4CVkf1bASfGKuYsaPSVM1qFok9RgsxWu0+SOto0OdZdafUWSyBCPug== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1666072984; a=rsa-sha256; cv=none; b=ir2LyMIgUTb3/2CJjbpaznIK44OVE4fP2Y5c+7wM62nSZBeU/JT1DP1QylA1Zn6gFDLuOV HDOtZ5b+WsN+z+dsgj+J0gBBjmeWF7iY34nNJmIiA6hIrcYr/fSrrois6NjP0LK6MCaxbh ihEXDZJl4xTGorMGXAqt5gYn6+jcL9zybgzJe7StH0zJhdGvEfSwzK4XvRWzPKGBUBbrc5 PuR9QRDn4sRnKOtNr06X6W7V23KmaKJnNZoqk7fjoqyObuETMsBhnWR6R7xSpPm8I7EP5q fvG33UQb9xS9uDlKEftOheNg8cTDld/w7ZzgowT6ZoEIvG+VBp/R1/AWN0sF2Q== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by cperciva: URL: https://cgit.FreeBSD.org/src/commit/?id=c32bd97641da2e49188e68fb83452605f6ace0ef commit c32bd97641da2e49188e68fb83452605f6ace0ef Author: Colin Percival AuthorDate: 2022-08-13 00:14:47 +0000 Commit: Colin Percival CommitDate: 2022-10-18 06:02:20 +0000 kern: Support duplicate variables in early kenv Some virtual machines pass virtio MMIO device parameters via the kernel command line as a series of virtio_mmio.device= options. These get translated into FreeBSD kernel environment variables; but unfortunately they all use the same variable name, which resulted in all but the first such parameter being ignored when the dynamic kernel environment is set up from the initial environment buffers. With this commit, duplicate environment settings will instead be stored as ${name}_1, ${name}_2... ${name}_9999. In the unlikely event that the same variable is set over 10000 times before the dynamic kernel environment is set up, we panic. Variable settings after the dynamic environment is initialized continue to override the previously-set value; the change is limited to the very early kernel boot (prior to SI_SUB_KMEM + 1) and changes behaviour from "ignore" to "store with a different name" only. Reviewed by: imp Feedback from: kevans Sponsored by: https://patreon.com/cperciva Differential Revision: https://reviews.freebsd.org/D36187 --- sys/kern/kern_environment.c | 68 +++++++++++++++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/sys/kern/kern_environment.c b/sys/kern/kern_environment.c index 77fdf833c530..f4c720aaaeb4 100644 --- a/sys/kern/kern_environment.c +++ b/sys/kern/kern_environment.c @@ -359,11 +359,33 @@ init_static_kenv(char *buf, size_t len) } } +/* Maximum suffix number appended for duplicate environment variable names. */ +#define MAXSUFFIX 9999 +#define SUFFIXLEN strlen("_" __XSTRING(MAXSUFFIX)) + +static void +getfreesuffix(char *cp, size_t *n) +{ + size_t len = strlen(cp); + char * ncp; + + ncp = malloc(len + SUFFIXLEN + 1, M_KENV, M_WAITOK); + memcpy(ncp, cp, len); + for (*n = 1; *n <= MAXSUFFIX; (*n)++) { + sprintf(&ncp[len], "_%zu", *n); + if (!_getenv_dynamic_locked(ncp, NULL)) + break; + } + free(ncp, M_KENV); + if (*n > MAXSUFFIX) + panic("Too many duplicate kernel environment values: %s", cp); +} + static void init_dynamic_kenv_from(char *init_env, int *curpos) { char *cp, *cpnext, *eqpos, *found; - size_t len; + size_t len, n; int i; if (init_env && *init_env != '\0') { @@ -372,6 +394,12 @@ init_dynamic_kenv_from(char *init_env, int *curpos) for (cp = init_env; cp != NULL; cp = cpnext) { cpnext = kernenv_next(cp); len = strlen(cp) + 1; + if (i > KENV_SIZE) { + printf( + "WARNING: too many kenv strings, ignoring %s\n", + cp); + goto sanitize; + } if (len > KENV_MNAMELEN + 1 + kenv_mvallen + 1) { printf( "WARNING: too long kenv string, ignoring %s\n", @@ -387,25 +415,31 @@ init_dynamic_kenv_from(char *init_env, int *curpos) } *eqpos = 0; /* - * De-dupe the environment as we go. We don't add the - * duplicated assignments because config(8) will flip - * the order of the static environment around to make - * kernel processing match the order of specification - * in the kernel config. + * Handle duplicates in the environment as we go; we + * add the duplicated assignments with _N suffixes. + * This ensures that (a) if a variable is set in the + * static environment and in the "loader" environment + * provided by MD code, the value from the loader will + * have the expected variable name and the value from + * the static environment will have the suffix; and (b) + * if the "loader" environment has the same variable + * set multiple times (as is possible with values being + * passed via the kernel "command line") the extra + * values are visible to code which knows where to look + * for them. */ found = _getenv_dynamic_locked(cp, NULL); - *eqpos = '='; - if (found != NULL) - goto sanitize; - if (i > KENV_SIZE) { - printf( - "WARNING: too many kenv strings, ignoring %s\n", - cp); - goto sanitize; + if (found != NULL) { + getfreesuffix(cp, &n); + kenvp[i] = malloc(len + SUFFIXLEN, + M_KENV, M_WAITOK); + sprintf(kenvp[i++], "%s_%zu=%s", cp, n, + &eqpos[1]); + } else { + kenvp[i] = malloc(len, M_KENV, M_WAITOK); + *eqpos = '='; + strcpy(kenvp[i++], cp); } - - kenvp[i] = malloc(len, M_KENV, M_WAITOK); - strcpy(kenvp[i++], cp); sanitize: #ifdef PRESERVE_EARLY_KENV continue;