1998-10-09 00:31:29 +00:00
|
|
|
/*-
|
2017-11-27 15:20:12 +00:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
|
|
|
*
|
1998-10-09 00:31:29 +00:00
|
|
|
* Copyright (c) 1998 Michael Smith
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
1998-10-09 11:03:46 +00:00
|
|
|
*/
|
1998-10-09 00:31:29 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The unified bootloader passes us a pointer to a preserved copy of
|
2002-04-17 13:06:36 +00:00
|
|
|
* bootstrap/kernel environment variables. We convert them to a
|
|
|
|
* dynamic array of strings later when the VM subsystem is up.
|
1998-10-09 00:31:29 +00:00
|
|
|
*
|
2002-04-17 13:06:36 +00:00
|
|
|
* We make these available through the kenv(2) syscall for userland
|
2014-10-16 18:04:43 +00:00
|
|
|
* and through kern_getenv()/freeenv() kern_setenv() kern_unsetenv() testenv() for
|
2002-04-17 13:06:36 +00:00
|
|
|
* the kernel.
|
1998-10-09 00:31:29 +00:00
|
|
|
*/
|
|
|
|
|
2003-06-11 00:56:59 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
1998-10-09 00:31:29 +00:00
|
|
|
#include <sys/param.h>
|
2002-04-17 13:06:36 +00:00
|
|
|
#include <sys/proc.h>
|
|
|
|
#include <sys/queue.h>
|
|
|
|
#include <sys/lock.h>
|
|
|
|
#include <sys/malloc.h>
|
|
|
|
#include <sys/mutex.h>
|
2006-11-06 13:42:10 +00:00
|
|
|
#include <sys/priv.h>
|
1998-10-09 00:31:29 +00:00
|
|
|
#include <sys/kernel.h>
|
|
|
|
#include <sys/systm.h>
|
2002-04-17 13:06:36 +00:00
|
|
|
#include <sys/sysent.h>
|
|
|
|
#include <sys/sysproto.h>
|
1998-10-09 00:31:29 +00:00
|
|
|
#include <sys/libkern.h>
|
2002-04-17 13:06:36 +00:00
|
|
|
#include <sys/kenv.h>
|
2018-06-20 20:04:20 +00:00
|
|
|
#include <sys/limits.h>
|
1998-10-09 00:31:29 +00:00
|
|
|
|
2006-10-22 11:52:19 +00:00
|
|
|
#include <security/mac/mac_framework.h>
|
|
|
|
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
static char *_getenv_dynamic_locked(const char *name, int *idx);
|
|
|
|
static char *_getenv_dynamic(const char *name, int *idx);
|
|
|
|
|
2005-02-10 12:02:37 +00:00
|
|
|
static MALLOC_DEFINE(M_KENV, "kenv", "kernel environment");
|
1998-10-09 00:31:29 +00:00
|
|
|
|
2002-04-17 13:06:36 +00:00
|
|
|
#define KENV_SIZE 512 /* Maximum number of environment strings */
|
|
|
|
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
/* pointer to the config-generated static environment */
|
2002-04-17 13:06:36 +00:00
|
|
|
char *kern_envp;
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
|
|
|
|
/* pointer to the md-static environment */
|
|
|
|
char *md_envp;
|
|
|
|
static int md_env_len;
|
|
|
|
static int md_env_pos;
|
|
|
|
|
2002-04-17 13:06:36 +00:00
|
|
|
static char *kernenv_next(char *);
|
|
|
|
|
|
|
|
/* dynamic environment variables */
|
|
|
|
char **kenvp;
|
2006-07-09 21:42:58 +00:00
|
|
|
struct mtx kenv_lock;
|
2002-04-17 13:06:36 +00:00
|
|
|
|
|
|
|
/*
|
2007-03-05 13:10:58 +00:00
|
|
|
* No need to protect this with a mutex since SYSINITS are single threaded.
|
2002-04-17 13:06:36 +00:00
|
|
|
*/
|
2018-07-10 02:43:22 +00:00
|
|
|
bool dynamic_kenv;
|
2002-04-17 13:06:36 +00:00
|
|
|
|
|
|
|
#define KENV_CHECK if (!dynamic_kenv) \
|
|
|
|
panic("%s: called before SI_SUB_KMEM", __func__)
|
|
|
|
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_kenv(td, uap)
|
2002-04-17 13:06:36 +00:00
|
|
|
struct thread *td;
|
|
|
|
struct kenv_args /* {
|
2002-12-14 02:07:32 +00:00
|
|
|
int what;
|
|
|
|
const char *name;
|
|
|
|
char *value;
|
|
|
|
int len;
|
2002-04-17 13:06:36 +00:00
|
|
|
} */ *uap;
|
|
|
|
{
|
2006-07-09 21:42:58 +00:00
|
|
|
char *name, *value, *buffer = NULL;
|
2009-03-23 00:00:50 +00:00
|
|
|
size_t len, done, needed, buflen;
|
2002-04-17 13:06:36 +00:00
|
|
|
int error, i;
|
2002-05-01 02:51:50 +00:00
|
|
|
|
2018-07-10 02:43:22 +00:00
|
|
|
KASSERT(dynamic_kenv, ("kenv: dynamic_kenv = false"));
|
2002-04-17 13:06:36 +00:00
|
|
|
|
|
|
|
error = 0;
|
2002-12-14 01:56:26 +00:00
|
|
|
if (uap->what == KENV_DUMP) {
|
2002-11-01 20:46:53 +00:00
|
|
|
#ifdef MAC
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_kenv_check_dump(td->td_ucred);
|
2002-11-01 20:46:53 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
#endif
|
2004-04-28 01:27:33 +00:00
|
|
|
done = needed = 0;
|
2009-03-23 00:00:50 +00:00
|
|
|
buflen = uap->len;
|
|
|
|
if (buflen > KENV_SIZE * (KENV_MNAMELEN + KENV_MVALLEN + 2))
|
|
|
|
buflen = KENV_SIZE * (KENV_MNAMELEN +
|
|
|
|
KENV_MVALLEN + 2);
|
2006-07-09 21:42:58 +00:00
|
|
|
if (uap->len > 0 && uap->value != NULL)
|
2009-03-23 00:00:50 +00:00
|
|
|
buffer = malloc(buflen, M_TEMP, M_WAITOK|M_ZERO);
|
2006-07-09 21:42:58 +00:00
|
|
|
mtx_lock(&kenv_lock);
|
2004-04-28 01:27:33 +00:00
|
|
|
for (i = 0; kenvp[i] != NULL; i++) {
|
|
|
|
len = strlen(kenvp[i]) + 1;
|
|
|
|
needed += len;
|
2009-03-23 00:00:50 +00:00
|
|
|
len = min(len, buflen - done);
|
2004-04-28 01:27:33 +00:00
|
|
|
/*
|
|
|
|
* If called with a NULL or insufficiently large
|
|
|
|
* buffer, just keep computing the required size.
|
|
|
|
*/
|
2006-07-09 21:42:58 +00:00
|
|
|
if (uap->value != NULL && buffer != NULL && len > 0) {
|
|
|
|
bcopy(kenvp[i], buffer + done, len);
|
2004-04-28 01:27:33 +00:00
|
|
|
done += len;
|
2002-04-17 13:06:36 +00:00
|
|
|
}
|
|
|
|
}
|
2006-07-09 21:42:58 +00:00
|
|
|
mtx_unlock(&kenv_lock);
|
|
|
|
if (buffer != NULL) {
|
|
|
|
error = copyout(buffer, uap->value, done);
|
|
|
|
free(buffer, M_TEMP);
|
|
|
|
}
|
2004-04-28 01:27:33 +00:00
|
|
|
td->td_retval[0] = ((done == needed) ? 0 : needed);
|
|
|
|
return (error);
|
2002-04-17 13:06:36 +00:00
|
|
|
}
|
|
|
|
|
2006-11-06 13:42:10 +00:00
|
|
|
switch (uap->what) {
|
|
|
|
case KENV_SET:
|
|
|
|
error = priv_check(td, PRIV_KENV_SET);
|
2002-04-17 13:06:36 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2006-11-06 13:42:10 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case KENV_UNSET:
|
|
|
|
error = priv_check(td, PRIV_KENV_UNSET);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
break;
|
2002-04-17 13:06:36 +00:00
|
|
|
}
|
|
|
|
|
2012-08-14 19:16:30 +00:00
|
|
|
name = malloc(KENV_MNAMELEN + 1, M_TEMP, M_WAITOK);
|
2002-04-17 13:06:36 +00:00
|
|
|
|
2012-08-14 19:16:30 +00:00
|
|
|
error = copyinstr(uap->name, name, KENV_MNAMELEN + 1, NULL);
|
2002-04-17 13:06:36 +00:00
|
|
|
if (error)
|
|
|
|
goto done;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
switch (uap->what) {
|
2002-04-17 13:06:36 +00:00
|
|
|
case KENV_GET:
|
2002-11-01 20:46:53 +00:00
|
|
|
#ifdef MAC
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_kenv_check_get(td->td_ucred, name);
|
2002-11-01 20:46:53 +00:00
|
|
|
if (error)
|
|
|
|
goto done;
|
|
|
|
#endif
|
2014-10-16 18:04:43 +00:00
|
|
|
value = kern_getenv(name);
|
2002-04-17 13:06:36 +00:00
|
|
|
if (value == NULL) {
|
|
|
|
error = ENOENT;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
len = strlen(value) + 1;
|
2002-12-14 01:56:26 +00:00
|
|
|
if (len > uap->len)
|
|
|
|
len = uap->len;
|
|
|
|
error = copyout(value, uap->value, len);
|
2002-04-17 13:06:36 +00:00
|
|
|
freeenv(value);
|
|
|
|
if (error)
|
|
|
|
goto done;
|
|
|
|
td->td_retval[0] = len;
|
|
|
|
break;
|
|
|
|
case KENV_SET:
|
2002-12-14 01:56:26 +00:00
|
|
|
len = uap->len;
|
2002-04-17 13:06:36 +00:00
|
|
|
if (len < 1) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto done;
|
|
|
|
}
|
2012-08-14 19:16:30 +00:00
|
|
|
if (len > KENV_MVALLEN + 1)
|
|
|
|
len = KENV_MVALLEN + 1;
|
2003-02-19 05:47:46 +00:00
|
|
|
value = malloc(len, M_TEMP, M_WAITOK);
|
2002-12-14 01:56:26 +00:00
|
|
|
error = copyinstr(uap->value, value, len, NULL);
|
2002-04-17 13:06:36 +00:00
|
|
|
if (error) {
|
|
|
|
free(value, M_TEMP);
|
|
|
|
goto done;
|
|
|
|
}
|
2002-11-01 20:46:53 +00:00
|
|
|
#ifdef MAC
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_kenv_check_set(td->td_ucred, name, value);
|
2002-11-01 20:46:53 +00:00
|
|
|
if (error == 0)
|
|
|
|
#endif
|
2014-10-16 18:04:43 +00:00
|
|
|
kern_setenv(name, value);
|
2002-04-17 13:06:36 +00:00
|
|
|
free(value, M_TEMP);
|
|
|
|
break;
|
|
|
|
case KENV_UNSET:
|
2002-11-01 20:46:53 +00:00
|
|
|
#ifdef MAC
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_kenv_check_unset(td->td_ucred, name);
|
2002-11-01 20:46:53 +00:00
|
|
|
if (error)
|
|
|
|
goto done;
|
|
|
|
#endif
|
2014-10-16 18:04:43 +00:00
|
|
|
error = kern_unsetenv(name);
|
2002-04-17 13:06:36 +00:00
|
|
|
if (error)
|
|
|
|
error = ENOENT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
done:
|
|
|
|
free(name, M_TEMP);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2016-01-02 02:53:48 +00:00
|
|
|
/*
|
|
|
|
* Populate the initial kernel environment.
|
|
|
|
*
|
|
|
|
* This is called very early in MD startup, either to provide a copy of the
|
|
|
|
* environment obtained from a boot loader, or to provide an empty buffer into
|
|
|
|
* which MD code can store an initial environment using kern_setenv() calls.
|
|
|
|
*
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
* kern_envp is set to the static_env generated by config(8). This implements
|
|
|
|
* the env keyword described in config(5).
|
2016-01-02 02:53:48 +00:00
|
|
|
*
|
|
|
|
* If len is non-zero, the caller is providing an empty buffer. The caller will
|
|
|
|
* subsequently use kern_setenv() to add up to len bytes of initial environment
|
|
|
|
* before the dynamic environment is available.
|
|
|
|
*
|
|
|
|
* If len is zero, the caller is providing a pre-loaded buffer containing
|
|
|
|
* environment strings. Additional strings cannot be added until the dynamic
|
|
|
|
* environment is available. The memory pointed to must remain stable at least
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
* until sysinit runs init_dynamic_kenv() and preferably until after SI_SUB_KMEM
|
|
|
|
* is finished so that subr_hints routines may continue to use it until the
|
|
|
|
* environments have been fully merged at the end of the pass. If no initial
|
|
|
|
* environment is available from the boot loader, passing a NULL pointer allows
|
|
|
|
* the static_env to be installed if it is configured. In this case, any call
|
|
|
|
* to kern_setenv() prior to the setup of the dynamic environment will result in
|
|
|
|
* a panic.
|
2016-01-02 02:53:48 +00:00
|
|
|
*/
|
2010-01-10 22:34:18 +00:00
|
|
|
void
|
|
|
|
init_static_kenv(char *buf, size_t len)
|
|
|
|
{
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
char *eval;
|
|
|
|
|
2018-11-13 04:34:30 +00:00
|
|
|
KASSERT(!dynamic_kenv, ("kenv: dynamic_kenv already initialized"));
|
2019-09-12 14:34:46 +00:00
|
|
|
/*
|
|
|
|
* Suitably sized means it must be able to hold at least one empty
|
|
|
|
* variable, otherwise things go belly up if a kern_getenv call is
|
|
|
|
* made without a prior call to kern_setenv as we have a malformed
|
|
|
|
* environment.
|
|
|
|
*/
|
|
|
|
KASSERT(len == 0 || len >= 2,
|
|
|
|
("kenv: static env must be initialized or suitably sized"));
|
|
|
|
KASSERT(len == 0 || (*buf == '\0' && *(buf + 1) == '\0'),
|
2019-09-12 13:51:43 +00:00
|
|
|
("kenv: sized buffer must be initially empty"));
|
2019-02-05 15:34:55 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We may be called twice, with the second call needed to relocate
|
|
|
|
* md_envp after enabling paging. md_envp is then garbage if it is
|
|
|
|
* not null and the relocation will move it. Discard it so as to
|
|
|
|
* not crash using its old value in our first call to kern_getenv().
|
|
|
|
*
|
|
|
|
* The second call gives the same environment as the first except
|
|
|
|
* in silly configurations where the static env disables itself.
|
|
|
|
*
|
|
|
|
* Other env calls don't handle possibly-garbage pointers, so must
|
|
|
|
* not be made between enabling paging and calling here.
|
|
|
|
*/
|
|
|
|
md_envp = NULL;
|
|
|
|
md_env_len = 0;
|
|
|
|
md_env_pos = 0;
|
|
|
|
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
/*
|
2018-07-12 02:51:50 +00:00
|
|
|
* Give the static environment a chance to disable the loader(8)
|
|
|
|
* environment first. This is done with loader_env.disabled=1.
|
|
|
|
*
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
* static_env and static_hints may both be disabled, but in slightly
|
|
|
|
* different ways. For static_env, we just don't setup kern_envp and
|
|
|
|
* it's as if a static env wasn't even provided. For static_hints,
|
|
|
|
* we effectively zero out the buffer to stop the rest of the kernel
|
|
|
|
* from being able to use it.
|
|
|
|
*
|
|
|
|
* We're intentionally setting this up so that static_hints.disabled may
|
|
|
|
* be specified in either the MD env or the static env. This keeps us
|
|
|
|
* consistent in our new world view.
|
2018-07-12 02:51:50 +00:00
|
|
|
*
|
|
|
|
* As a warning, the static environment may not be disabled in any way
|
|
|
|
* if the static environment has disabled the loader environment.
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
*/
|
2018-07-12 02:51:50 +00:00
|
|
|
kern_envp = static_env;
|
|
|
|
eval = kern_getenv("loader_env.disabled");
|
|
|
|
if (eval == NULL || strcmp(eval, "1") != 0) {
|
|
|
|
md_envp = buf;
|
|
|
|
md_env_len = len;
|
|
|
|
md_env_pos = 0;
|
|
|
|
|
|
|
|
eval = kern_getenv("static_env.disabled");
|
2019-02-05 15:34:55 +00:00
|
|
|
if (eval != NULL && strcmp(eval, "1") == 0) {
|
|
|
|
kern_envp[0] = '\0';
|
|
|
|
kern_envp[1] = '\0';
|
|
|
|
}
|
2018-07-12 02:51:50 +00:00
|
|
|
}
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
eval = kern_getenv("static_hints.disabled");
|
2019-02-05 15:34:55 +00:00
|
|
|
if (eval != NULL && strcmp(eval, "1") == 0) {
|
|
|
|
static_hints[0] = '\0';
|
|
|
|
static_hints[1] = '\0';
|
|
|
|
}
|
2010-01-10 22:34:18 +00:00
|
|
|
}
|
|
|
|
|
2002-04-17 13:06:36 +00:00
|
|
|
static void
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
init_dynamic_kenv_from(char *init_env, int *curpos)
|
2002-04-17 13:06:36 +00:00
|
|
|
{
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
char *cp, *cpnext, *eqpos, *found;
|
2011-05-23 16:40:44 +00:00
|
|
|
size_t len;
|
|
|
|
int i;
|
2002-04-17 13:06:36 +00:00
|
|
|
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
if (init_env && *init_env != '\0') {
|
|
|
|
found = NULL;
|
|
|
|
i = *curpos;
|
|
|
|
for (cp = init_env; cp != NULL; cp = cpnext) {
|
2014-10-22 23:35:32 +00:00
|
|
|
cpnext = kernenv_next(cp);
|
2013-04-12 15:58:53 +00:00
|
|
|
len = strlen(cp) + 1;
|
|
|
|
if (len > KENV_MNAMELEN + 1 + KENV_MVALLEN + 1) {
|
|
|
|
printf(
|
|
|
|
"WARNING: too long kenv string, ignoring %s\n",
|
|
|
|
cp);
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
goto sanitize;
|
2013-04-12 15:58:53 +00:00
|
|
|
}
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
eqpos = strchr(cp, '=');
|
|
|
|
if (eqpos == NULL) {
|
|
|
|
printf(
|
|
|
|
"WARNING: malformed static env value, ignoring %s\n",
|
|
|
|
cp);
|
|
|
|
goto sanitize;
|
|
|
|
}
|
|
|
|
*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.
|
|
|
|
*/
|
|
|
|
found = _getenv_dynamic_locked(cp, NULL);
|
|
|
|
*eqpos = '=';
|
|
|
|
if (found != NULL)
|
|
|
|
goto sanitize;
|
|
|
|
if (i > KENV_SIZE) {
|
2013-04-12 15:58:53 +00:00
|
|
|
printf(
|
|
|
|
"WARNING: too many kenv strings, ignoring %s\n",
|
|
|
|
cp);
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
goto sanitize;
|
|
|
|
}
|
|
|
|
|
|
|
|
kenvp[i] = malloc(len, M_KENV, M_WAITOK);
|
|
|
|
strcpy(kenvp[i++], cp);
|
|
|
|
sanitize:
|
|
|
|
explicit_bzero(cp, len - 1);
|
2011-05-23 16:40:44 +00:00
|
|
|
}
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
*curpos = i;
|
2002-04-17 13:06:36 +00:00
|
|
|
}
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Setup the dynamic kernel environment.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
init_dynamic_kenv(void *data __unused)
|
|
|
|
{
|
|
|
|
int dynamic_envpos;
|
|
|
|
|
|
|
|
kenvp = malloc((KENV_SIZE + 1) * sizeof(char *), M_KENV,
|
|
|
|
M_WAITOK | M_ZERO);
|
|
|
|
|
|
|
|
dynamic_envpos = 0;
|
|
|
|
init_dynamic_kenv_from(md_envp, &dynamic_envpos);
|
|
|
|
init_dynamic_kenv_from(kern_envp, &dynamic_envpos);
|
|
|
|
kenvp[dynamic_envpos] = NULL;
|
2002-04-17 13:06:36 +00:00
|
|
|
|
2006-07-09 21:42:58 +00:00
|
|
|
mtx_init(&kenv_lock, "kernel environment", NULL, MTX_DEF);
|
2018-07-10 02:43:22 +00:00
|
|
|
dynamic_kenv = true;
|
2002-04-17 13:06:36 +00:00
|
|
|
}
|
2018-07-06 16:51:35 +00:00
|
|
|
SYSINIT(kenv, SI_SUB_KMEM + 1, SI_ORDER_FIRST, init_dynamic_kenv, NULL);
|
2002-04-17 13:06:36 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
freeenv(char *env)
|
|
|
|
{
|
|
|
|
|
2014-10-23 18:23:50 +00:00
|
|
|
if (dynamic_kenv && env != NULL) {
|
2018-04-10 22:57:56 +00:00
|
|
|
explicit_bzero(env, strlen(env));
|
2002-04-17 13:06:36 +00:00
|
|
|
free(env, M_KENV);
|
2014-10-22 23:35:32 +00:00
|
|
|
}
|
2002-04-17 13:06:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Internal functions for string lookup.
|
|
|
|
*/
|
|
|
|
static char *
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
_getenv_dynamic_locked(const char *name, int *idx)
|
2002-04-17 13:06:36 +00:00
|
|
|
{
|
|
|
|
char *cp;
|
|
|
|
int len, i;
|
|
|
|
|
|
|
|
len = strlen(name);
|
|
|
|
for (cp = kenvp[0], i = 0; cp != NULL; cp = kenvp[++i]) {
|
2005-09-26 14:14:55 +00:00
|
|
|
if ((strncmp(cp, name, len) == 0) &&
|
|
|
|
(cp[len] == '=')) {
|
2002-04-17 13:06:36 +00:00
|
|
|
if (idx != NULL)
|
|
|
|
*idx = i;
|
|
|
|
return (cp + len + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
_getenv_dynamic(const char *name, int *idx)
|
|
|
|
{
|
|
|
|
|
|
|
|
mtx_assert(&kenv_lock, MA_OWNED);
|
|
|
|
return (_getenv_dynamic_locked(name, idx));
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
_getenv_static_from(char *chkenv, const char *name)
|
2002-04-17 13:06:36 +00:00
|
|
|
{
|
|
|
|
char *cp, *ep;
|
|
|
|
int len;
|
|
|
|
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
for (cp = chkenv; cp != NULL; cp = kernenv_next(cp)) {
|
2002-04-17 13:06:36 +00:00
|
|
|
for (ep = cp; (*ep != '=') && (*ep != 0); ep++)
|
|
|
|
;
|
2002-04-25 20:25:15 +00:00
|
|
|
if (*ep != '=')
|
|
|
|
continue;
|
2002-04-17 13:06:36 +00:00
|
|
|
len = ep - cp;
|
2002-04-25 20:25:15 +00:00
|
|
|
ep++;
|
|
|
|
if (!strncmp(name, cp, len) && name[len] == 0)
|
2002-04-17 13:06:36 +00:00
|
|
|
return (ep);
|
|
|
|
}
|
|
|
|
return (NULL);
|
|
|
|
}
|
1998-10-09 00:31:29 +00:00
|
|
|
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
static char *
|
|
|
|
_getenv_static(const char *name)
|
|
|
|
{
|
|
|
|
char *val;
|
|
|
|
|
|
|
|
val = _getenv_static_from(md_envp, name);
|
|
|
|
if (val != NULL)
|
|
|
|
return (val);
|
|
|
|
val = _getenv_static_from(kern_envp, name);
|
|
|
|
if (val != NULL)
|
|
|
|
return (val);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
2001-10-23 22:34:36 +00:00
|
|
|
/*
|
|
|
|
* Look up an environment variable by name.
|
2002-04-17 13:06:36 +00:00
|
|
|
* Return a pointer to the string if found.
|
|
|
|
* The pointer has to be freed with freeenv()
|
|
|
|
* after use.
|
2001-10-23 22:34:36 +00:00
|
|
|
*/
|
1998-10-09 00:31:29 +00:00
|
|
|
char *
|
2014-10-16 18:04:43 +00:00
|
|
|
kern_getenv(const char *name)
|
1998-10-09 00:31:29 +00:00
|
|
|
{
|
2002-04-17 17:51:10 +00:00
|
|
|
char buf[KENV_MNAMELEN + 1 + KENV_MVALLEN + 1];
|
2013-11-01 10:32:33 +00:00
|
|
|
char *ret;
|
2002-04-17 13:06:36 +00:00
|
|
|
|
|
|
|
if (dynamic_kenv) {
|
2013-11-01 10:32:33 +00:00
|
|
|
if (getenv_string(name, buf, sizeof(buf))) {
|
|
|
|
ret = strdup(buf, M_KENV);
|
2002-04-17 17:51:10 +00:00
|
|
|
} else {
|
2002-04-17 13:06:36 +00:00
|
|
|
ret = NULL;
|
2011-05-07 17:59:07 +00:00
|
|
|
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
|
|
|
|
"getenv");
|
2002-04-17 17:51:10 +00:00
|
|
|
}
|
2002-04-17 13:06:36 +00:00
|
|
|
} else
|
|
|
|
ret = _getenv_static(name);
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Test if an environment variable is defined.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
testenv(const char *name)
|
|
|
|
{
|
|
|
|
char *cp;
|
|
|
|
|
|
|
|
if (dynamic_kenv) {
|
2006-07-09 21:42:58 +00:00
|
|
|
mtx_lock(&kenv_lock);
|
2002-04-17 13:06:36 +00:00
|
|
|
cp = _getenv_dynamic(name, NULL);
|
2006-07-09 21:42:58 +00:00
|
|
|
mtx_unlock(&kenv_lock);
|
2002-04-17 13:06:36 +00:00
|
|
|
} else
|
|
|
|
cp = _getenv_static(name);
|
|
|
|
if (cp != NULL)
|
|
|
|
return (1);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
/*
|
|
|
|
* Set an environment variable in the MD-static environment. This cannot
|
|
|
|
* feasibly be done on config(8)-generated static environments as they don't
|
|
|
|
* generally include space for extra variables.
|
|
|
|
*/
|
2010-01-10 22:34:18 +00:00
|
|
|
static int
|
|
|
|
setenv_static(const char *name, const char *value)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
if (md_env_pos >= md_env_len)
|
2010-01-10 22:34:18 +00:00
|
|
|
return (-1);
|
|
|
|
|
|
|
|
/* Check space for x=y and two nuls */
|
|
|
|
len = strlen(name) + strlen(value);
|
kern_environment: use any provided environments, evict hintmode/envmode
At the moment, hintmode and envmode are used to indicate whether static
hints or static env have been provided in the kernel config(5) and the
static versions are mutually exclusive with loader(8)-provided environment.
hintmode *can* be reconfigured later to pull from the dynamic environment,
thus taking advantage of the loader(8) or post-kmem environment setting.
This changeset fixes both problems at once to move us from a semi-confusing
state to a consistent state: if an environment file, hints file, or
loader(8) environment are provided, we use them in a well-known order of
precedence:
- loader(8) environment
- static environment
- static hints file
Once the dynamic environment is setup this becomes a moot point. The
loader(8) and static environments are merged (respecting the above order of
precedence), and the static hints are merged in on an as-needed basis after
the dynamic environment has been setup.
Hints lookup are changed to respect all of the above. Before the dynamic
environment is setup, lookups use the above-mentioned order and fallback to
the next environment if a matching hint is not found. Once the dynamic
environment is setup, that is used on its own since it captures all of the
above information plus any dynamic kenv settings that came up later in boot.
The following tangentially related changes were made to res_find:
- A hintp cookie is now passed in so that related searches continue using
the chain of environments (or dynamic environment) without relying on
global state
- All three environments will be searched if they actually have valid hints
to use, rather than just choosing the first environment that actually had
a hint and rolling with that only
The hintmode sysctl has been ripped out. static_{env,hints}.disabled are
still honored and will disable their respective environments from being used
for hint lookups and from being merged into the dynamic environment, as
expected.
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D15953
2018-07-05 16:30:32 +00:00
|
|
|
if (len + 3 < md_env_len - md_env_pos) {
|
|
|
|
len = sprintf(&md_envp[md_env_pos], "%s=%s", name, value);
|
|
|
|
md_env_pos += len+1;
|
|
|
|
md_envp[md_env_pos] = '\0';
|
2010-01-10 22:34:18 +00:00
|
|
|
return (0);
|
|
|
|
} else
|
|
|
|
return (-1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2002-04-17 13:06:36 +00:00
|
|
|
/*
|
|
|
|
* Set an environment variable by name.
|
|
|
|
*/
|
2002-04-17 17:51:10 +00:00
|
|
|
int
|
2014-10-16 18:04:43 +00:00
|
|
|
kern_setenv(const char *name, const char *value)
|
2002-04-17 13:06:36 +00:00
|
|
|
{
|
2002-04-17 17:51:10 +00:00
|
|
|
char *buf, *cp, *oldenv;
|
|
|
|
int namelen, vallen, i;
|
2002-04-17 13:06:36 +00:00
|
|
|
|
2018-07-10 02:43:22 +00:00
|
|
|
if (!dynamic_kenv && md_env_len > 0)
|
2010-01-10 22:34:18 +00:00
|
|
|
return (setenv_static(name, value));
|
|
|
|
|
2002-04-17 13:06:36 +00:00
|
|
|
KENV_CHECK;
|
|
|
|
|
2002-04-17 17:51:10 +00:00
|
|
|
namelen = strlen(name) + 1;
|
2012-08-14 19:16:30 +00:00
|
|
|
if (namelen > KENV_MNAMELEN + 1)
|
2002-04-17 17:51:10 +00:00
|
|
|
return (-1);
|
|
|
|
vallen = strlen(value) + 1;
|
2012-08-14 19:16:30 +00:00
|
|
|
if (vallen > KENV_MVALLEN + 1)
|
2002-04-17 17:51:10 +00:00
|
|
|
return (-1);
|
2003-02-19 05:47:46 +00:00
|
|
|
buf = malloc(namelen + vallen, M_KENV, M_WAITOK);
|
2002-04-17 13:06:36 +00:00
|
|
|
sprintf(buf, "%s=%s", name, value);
|
|
|
|
|
2006-07-09 21:42:58 +00:00
|
|
|
mtx_lock(&kenv_lock);
|
2002-04-17 13:06:36 +00:00
|
|
|
cp = _getenv_dynamic(name, &i);
|
|
|
|
if (cp != NULL) {
|
2002-04-17 17:51:10 +00:00
|
|
|
oldenv = kenvp[i];
|
2002-04-17 13:06:36 +00:00
|
|
|
kenvp[i] = buf;
|
2006-07-09 21:42:58 +00:00
|
|
|
mtx_unlock(&kenv_lock);
|
2002-04-17 17:51:10 +00:00
|
|
|
free(oldenv, M_KENV);
|
2002-04-17 13:06:36 +00:00
|
|
|
} else {
|
|
|
|
/* We add the option if it wasn't found */
|
|
|
|
for (i = 0; (cp = kenvp[i]) != NULL; i++)
|
|
|
|
;
|
2005-07-31 10:28:35 +00:00
|
|
|
|
|
|
|
/* Bounds checking */
|
|
|
|
if (i < 0 || i >= KENV_SIZE) {
|
|
|
|
free(buf, M_KENV);
|
2006-07-09 21:42:58 +00:00
|
|
|
mtx_unlock(&kenv_lock);
|
2005-07-31 10:28:35 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
2002-04-17 13:06:36 +00:00
|
|
|
kenvp[i] = buf;
|
|
|
|
kenvp[i + 1] = NULL;
|
2006-07-09 21:42:58 +00:00
|
|
|
mtx_unlock(&kenv_lock);
|
2002-04-17 13:06:36 +00:00
|
|
|
}
|
2002-04-17 17:51:10 +00:00
|
|
|
return (0);
|
2002-04-17 13:06:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unset an environment variable string.
|
|
|
|
*/
|
|
|
|
int
|
2014-10-16 18:04:43 +00:00
|
|
|
kern_unsetenv(const char *name)
|
2002-04-17 13:06:36 +00:00
|
|
|
{
|
2002-04-17 17:51:10 +00:00
|
|
|
char *cp, *oldenv;
|
2002-04-17 13:06:36 +00:00
|
|
|
int i, j;
|
|
|
|
|
|
|
|
KENV_CHECK;
|
|
|
|
|
2006-07-09 21:42:58 +00:00
|
|
|
mtx_lock(&kenv_lock);
|
2002-04-17 13:06:36 +00:00
|
|
|
cp = _getenv_dynamic(name, &i);
|
|
|
|
if (cp != NULL) {
|
2002-04-17 17:51:10 +00:00
|
|
|
oldenv = kenvp[i];
|
2002-04-17 13:06:36 +00:00
|
|
|
for (j = i + 1; kenvp[j] != NULL; j++)
|
|
|
|
kenvp[i++] = kenvp[j];
|
|
|
|
kenvp[i] = NULL;
|
2006-07-09 21:42:58 +00:00
|
|
|
mtx_unlock(&kenv_lock);
|
2018-04-10 22:57:56 +00:00
|
|
|
explicit_bzero(oldenv, strlen(oldenv));
|
2002-04-17 17:51:10 +00:00
|
|
|
free(oldenv, M_KENV);
|
2002-04-17 13:06:36 +00:00
|
|
|
return (0);
|
|
|
|
}
|
2006-07-09 21:42:58 +00:00
|
|
|
mtx_unlock(&kenv_lock);
|
2002-04-17 13:06:36 +00:00
|
|
|
return (-1);
|
1998-10-09 00:31:29 +00:00
|
|
|
}
|
|
|
|
|
2001-10-23 22:34:36 +00:00
|
|
|
/*
|
|
|
|
* Return a string value from an environment variable.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
getenv_string(const char *name, char *data, int size)
|
|
|
|
{
|
2013-11-01 10:32:33 +00:00
|
|
|
char *cp;
|
2001-10-23 22:34:36 +00:00
|
|
|
|
2013-11-01 10:32:33 +00:00
|
|
|
if (dynamic_kenv) {
|
|
|
|
mtx_lock(&kenv_lock);
|
|
|
|
cp = _getenv_dynamic(name, NULL);
|
|
|
|
if (cp != NULL)
|
|
|
|
strlcpy(data, cp, size);
|
|
|
|
mtx_unlock(&kenv_lock);
|
|
|
|
} else {
|
|
|
|
cp = _getenv_static(name);
|
|
|
|
if (cp != NULL)
|
|
|
|
strlcpy(data, cp, size);
|
|
|
|
}
|
|
|
|
return (cp != NULL);
|
2001-10-23 22:34:36 +00:00
|
|
|
}
|
|
|
|
|
2018-06-20 20:04:20 +00:00
|
|
|
/*
|
|
|
|
* Return an array of integers at the given type size and signedness.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
getenv_array(const char *name, void *pdata, int size, int *psize,
|
|
|
|
int type_size, bool allow_signed)
|
|
|
|
{
|
|
|
|
char buf[KENV_MNAMELEN + 1 + KENV_MVALLEN + 1];
|
|
|
|
uint8_t shift;
|
|
|
|
int64_t value;
|
|
|
|
int64_t old;
|
|
|
|
char *end;
|
|
|
|
char *ptr;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
if (getenv_string(name, buf, sizeof(buf)) == 0)
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
/* get maximum number of elements */
|
|
|
|
size /= type_size;
|
|
|
|
|
|
|
|
n = 0;
|
|
|
|
|
|
|
|
for (ptr = buf; *ptr != 0; ) {
|
|
|
|
|
|
|
|
value = strtoq(ptr, &end, 0);
|
|
|
|
|
|
|
|
/* check if signed numbers are allowed */
|
|
|
|
if (value < 0 && !allow_signed)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
/* check for invalid value */
|
|
|
|
if (ptr == end)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
/* check for valid suffix */
|
|
|
|
switch (*end) {
|
|
|
|
case 't':
|
|
|
|
case 'T':
|
|
|
|
shift = 40;
|
|
|
|
end++;
|
|
|
|
break;
|
|
|
|
case 'g':
|
|
|
|
case 'G':
|
|
|
|
shift = 30;
|
|
|
|
end++;
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
case 'M':
|
|
|
|
shift = 20;
|
|
|
|
end++;
|
|
|
|
break;
|
|
|
|
case 'k':
|
|
|
|
case 'K':
|
|
|
|
shift = 10;
|
|
|
|
end++;
|
|
|
|
break;
|
|
|
|
case ' ':
|
|
|
|
case '\t':
|
|
|
|
case ',':
|
|
|
|
case 0:
|
|
|
|
shift = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* garbage after numeric value */
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* skip till next value, if any */
|
|
|
|
while (*end == '\t' || *end == ',' || *end == ' ')
|
|
|
|
end++;
|
|
|
|
|
|
|
|
/* update pointer */
|
|
|
|
ptr = end;
|
|
|
|
|
|
|
|
/* apply shift */
|
|
|
|
old = value;
|
|
|
|
value <<= shift;
|
|
|
|
|
|
|
|
/* overflow check */
|
|
|
|
if ((value >> shift) != old)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
/* check for buffer overflow */
|
|
|
|
if (n >= size)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
/* store value according to type size */
|
|
|
|
switch (type_size) {
|
|
|
|
case 1:
|
|
|
|
if (allow_signed) {
|
|
|
|
if (value < SCHAR_MIN || value > SCHAR_MAX)
|
|
|
|
goto error;
|
|
|
|
} else {
|
|
|
|
if (value < 0 || value > UCHAR_MAX)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
((uint8_t *)pdata)[n] = (uint8_t)value;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if (allow_signed) {
|
|
|
|
if (value < SHRT_MIN || value > SHRT_MAX)
|
|
|
|
goto error;
|
|
|
|
} else {
|
|
|
|
if (value < 0 || value > USHRT_MAX)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
((uint16_t *)pdata)[n] = (uint16_t)value;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
if (allow_signed) {
|
|
|
|
if (value < INT_MIN || value > INT_MAX)
|
|
|
|
goto error;
|
|
|
|
} else {
|
|
|
|
if (value > UINT_MAX)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
((uint32_t *)pdata)[n] = (uint32_t)value;
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
((uint64_t *)pdata)[n] = (uint64_t)value;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
*psize = n * type_size;
|
|
|
|
|
|
|
|
if (n != 0)
|
|
|
|
return (1); /* success */
|
|
|
|
error:
|
|
|
|
return (0); /* failure */
|
|
|
|
}
|
|
|
|
|
1999-01-15 17:25:02 +00:00
|
|
|
/*
|
|
|
|
* Return an integer value from an environment variable.
|
|
|
|
*/
|
|
|
|
int
|
2001-06-15 07:29:17 +00:00
|
|
|
getenv_int(const char *name, int *data)
|
1999-11-07 01:10:30 +00:00
|
|
|
{
|
2002-05-01 02:51:50 +00:00
|
|
|
quad_t tmp;
|
|
|
|
int rval;
|
|
|
|
|
|
|
|
rval = getenv_quad(name, &tmp);
|
|
|
|
if (rval)
|
|
|
|
*data = (int) tmp;
|
|
|
|
return (rval);
|
1999-11-07 01:10:30 +00:00
|
|
|
}
|
|
|
|
|
2007-10-13 11:30:19 +00:00
|
|
|
/*
|
|
|
|
* Return an unsigned integer value from an environment variable.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
getenv_uint(const char *name, unsigned int *data)
|
|
|
|
{
|
|
|
|
quad_t tmp;
|
|
|
|
int rval;
|
|
|
|
|
|
|
|
rval = getenv_quad(name, &tmp);
|
|
|
|
if (rval)
|
|
|
|
*data = (unsigned int) tmp;
|
|
|
|
return (rval);
|
|
|
|
}
|
|
|
|
|
2016-04-15 03:09:55 +00:00
|
|
|
/*
|
|
|
|
* Return an int64_t value from an environment variable.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
getenv_int64(const char *name, int64_t *data)
|
|
|
|
{
|
|
|
|
quad_t tmp;
|
|
|
|
int64_t rval;
|
|
|
|
|
|
|
|
rval = getenv_quad(name, &tmp);
|
|
|
|
if (rval)
|
|
|
|
*data = (int64_t) tmp;
|
|
|
|
return (rval);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return an uint64_t value from an environment variable.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
getenv_uint64(const char *name, uint64_t *data)
|
|
|
|
{
|
|
|
|
quad_t tmp;
|
|
|
|
uint64_t rval;
|
|
|
|
|
|
|
|
rval = getenv_quad(name, &tmp);
|
|
|
|
if (rval)
|
|
|
|
*data = (uint64_t) tmp;
|
|
|
|
return (rval);
|
|
|
|
}
|
|
|
|
|
2004-10-31 15:50:33 +00:00
|
|
|
/*
|
|
|
|
* Return a long value from an environment variable.
|
|
|
|
*/
|
2007-10-13 11:30:19 +00:00
|
|
|
int
|
2004-10-31 15:50:33 +00:00
|
|
|
getenv_long(const char *name, long *data)
|
|
|
|
{
|
|
|
|
quad_t tmp;
|
2007-10-13 11:30:19 +00:00
|
|
|
int rval;
|
2004-10-31 15:50:33 +00:00
|
|
|
|
|
|
|
rval = getenv_quad(name, &tmp);
|
|
|
|
if (rval)
|
|
|
|
*data = (long) tmp;
|
|
|
|
return (rval);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return an unsigned long value from an environment variable.
|
|
|
|
*/
|
2007-10-13 11:30:19 +00:00
|
|
|
int
|
2004-10-31 15:50:33 +00:00
|
|
|
getenv_ulong(const char *name, unsigned long *data)
|
|
|
|
{
|
|
|
|
quad_t tmp;
|
2007-10-13 11:30:19 +00:00
|
|
|
int rval;
|
2004-10-31 15:50:33 +00:00
|
|
|
|
|
|
|
rval = getenv_quad(name, &tmp);
|
|
|
|
if (rval)
|
|
|
|
*data = (unsigned long) tmp;
|
|
|
|
return (rval);
|
|
|
|
}
|
|
|
|
|
1999-11-07 01:10:30 +00:00
|
|
|
/*
|
|
|
|
* Return a quad_t value from an environment variable.
|
|
|
|
*/
|
2001-10-23 22:34:36 +00:00
|
|
|
int
|
2001-06-15 07:29:17 +00:00
|
|
|
getenv_quad(const char *name, quad_t *data)
|
1999-01-15 17:25:02 +00:00
|
|
|
{
|
2013-11-01 10:32:33 +00:00
|
|
|
char value[KENV_MNAMELEN + 1 + KENV_MVALLEN + 1];
|
2002-05-01 02:51:50 +00:00
|
|
|
char *vtp;
|
|
|
|
quad_t iv;
|
|
|
|
|
2013-11-01 10:32:33 +00:00
|
|
|
if (!getenv_string(name, value, sizeof(value)))
|
2002-05-01 02:51:50 +00:00
|
|
|
return (0);
|
|
|
|
iv = strtoq(value, &vtp, 0);
|
2013-11-01 10:32:33 +00:00
|
|
|
if (vtp == value || (vtp[0] != '\0' && vtp[1] != '\0'))
|
2005-03-05 15:52:12 +00:00
|
|
|
return (0);
|
|
|
|
switch (vtp[0]) {
|
|
|
|
case 't': case 'T':
|
|
|
|
iv *= 1024;
|
2018-10-25 15:43:21 +00:00
|
|
|
/* FALLTHROUGH */
|
2005-03-05 15:52:12 +00:00
|
|
|
case 'g': case 'G':
|
|
|
|
iv *= 1024;
|
2018-10-25 15:43:21 +00:00
|
|
|
/* FALLTHROUGH */
|
2005-03-05 15:52:12 +00:00
|
|
|
case 'm': case 'M':
|
|
|
|
iv *= 1024;
|
2018-10-25 15:43:21 +00:00
|
|
|
/* FALLTHROUGH */
|
2005-03-05 15:52:12 +00:00
|
|
|
case 'k': case 'K':
|
|
|
|
iv *= 1024;
|
|
|
|
case '\0':
|
|
|
|
break;
|
|
|
|
default:
|
2002-05-01 02:51:50 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
*data = iv;
|
|
|
|
return (1);
|
1999-01-15 17:25:02 +00:00
|
|
|
}
|
1998-10-09 00:31:29 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Find the next entry after the one which (cp) falls within, return a
|
|
|
|
* pointer to its start or NULL if there are no more.
|
|
|
|
*/
|
|
|
|
static char *
|
|
|
|
kernenv_next(char *cp)
|
|
|
|
{
|
2002-05-01 02:51:50 +00:00
|
|
|
|
|
|
|
if (cp != NULL) {
|
|
|
|
while (*cp != 0)
|
|
|
|
cp++;
|
|
|
|
cp++;
|
|
|
|
if (*cp == 0)
|
|
|
|
cp = NULL;
|
|
|
|
}
|
|
|
|
return (cp);
|
1998-10-09 00:31:29 +00:00
|
|
|
}
|
|
|
|
|
2001-06-08 05:24:21 +00:00
|
|
|
void
|
|
|
|
tunable_int_init(void *data)
|
|
|
|
{
|
|
|
|
struct tunable_int *d = (struct tunable_int *)data;
|
|
|
|
|
|
|
|
TUNABLE_INT_FETCH(d->path, d->var);
|
|
|
|
}
|
|
|
|
|
2004-10-31 15:50:33 +00:00
|
|
|
void
|
|
|
|
tunable_long_init(void *data)
|
|
|
|
{
|
|
|
|
struct tunable_long *d = (struct tunable_long *)data;
|
|
|
|
|
|
|
|
TUNABLE_LONG_FETCH(d->path, d->var);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
tunable_ulong_init(void *data)
|
|
|
|
{
|
|
|
|
struct tunable_ulong *d = (struct tunable_ulong *)data;
|
|
|
|
|
|
|
|
TUNABLE_ULONG_FETCH(d->path, d->var);
|
|
|
|
}
|
|
|
|
|
2016-04-15 03:09:55 +00:00
|
|
|
void
|
|
|
|
tunable_int64_init(void *data)
|
|
|
|
{
|
|
|
|
struct tunable_int64 *d = (struct tunable_int64 *)data;
|
|
|
|
|
|
|
|
TUNABLE_INT64_FETCH(d->path, d->var);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
tunable_uint64_init(void *data)
|
|
|
|
{
|
|
|
|
struct tunable_uint64 *d = (struct tunable_uint64 *)data;
|
|
|
|
|
|
|
|
TUNABLE_UINT64_FETCH(d->path, d->var);
|
|
|
|
}
|
|
|
|
|
2008-07-21 15:05:25 +00:00
|
|
|
void
|
|
|
|
tunable_quad_init(void *data)
|
|
|
|
{
|
|
|
|
struct tunable_quad *d = (struct tunable_quad *)data;
|
|
|
|
|
|
|
|
TUNABLE_QUAD_FETCH(d->path, d->var);
|
|
|
|
}
|
|
|
|
|
2001-06-08 05:24:21 +00:00
|
|
|
void
|
|
|
|
tunable_str_init(void *data)
|
|
|
|
{
|
|
|
|
struct tunable_str *d = (struct tunable_str *)data;
|
|
|
|
|
|
|
|
TUNABLE_STR_FETCH(d->path, d->var, d->size);
|
|
|
|
}
|