46#include <sys/malloc.h>
50#include <sys/kernel.h>
52#include <sys/sysent.h>
53#include <sys/sysproto.h>
54#include <sys/libkern.h>
56#include <sys/limits.h>
58#include <security/mac/mac_framework.h>
92#define KENV_CHECK if (!dynamic_kenv) \
93 panic("%s: called before SI_SUB_KMEM", __func__)
99 size_t done, needed, buflen;
106 MPASS(what == KENV_DUMP || what == KENV_DUMP_LOADER ||
107 what == KENV_DUMP_STATIC);
115 if (what != KENV_DUMP) {
124 if (len > 0 &&
value != NULL)
125 buffer =
malloc(buflen, M_TEMP, M_WAITOK|M_ZERO);
128 if (what == KENV_DUMP)
130 while (*envp != NULL) {
131 len = strlen(*envp) + 1;
133 len = min(len, buflen - done);
138 if (
value != NULL && buffer != NULL && len > 0) {
139 bcopy(*envp, buffer + done, len);
144 if (what == KENV_DUMP)
149 if (what == KENV_DUMP)
151 if (buffer != NULL) {
152 error = copyout(buffer,
value, done);
153 free(buffer, M_TEMP);
155 td->td_retval[0] = ((done == needed) ? 0 : needed);
173 error = mac_kenv_check_dump(td->td_ucred);
178 case KENV_DUMP_LOADER:
179 case KENV_DUMP_STATIC:
181 error = mac_kenv_check_dump(td->td_ucred);
185#ifdef PRESERVE_EARLY_KENV
187 uap->what == KENV_DUMP_LOADER ? (
char **)
md_envp :
188 (
char **)
kern_envp, uap->what, uap->value, uap->len));
205 name =
malloc(KENV_MNAMELEN + 1, M_TEMP, M_WAITOK);
207 error = copyinstr(uap->name,
name, KENV_MNAMELEN + 1, NULL);
214 error = mac_kenv_check_get(td->td_ucred,
name);
223 len = strlen(
value) + 1;
226 error = copyout(
value, uap->value, len);
230 td->td_retval[0] = len;
241 error = copyinstr(uap->value,
value, len, NULL);
247 error = mac_kenv_check_set(td->td_ucred,
name,
value);
255 error = mac_kenv_check_unset(td->td_ucred,
name);
301 KASSERT(!
dynamic_kenv, (
"kenv: dynamic_kenv already initialized"));
308 KASSERT(len == 0 || len >= 2,
309 (
"kenv: static env must be initialized or suitably sized"));
310 KASSERT(len == 0 || (*
buf ==
'\0' && *(
buf + 1) ==
'\0'),
311 (
"kenv: sized buffer must be initially empty"));
358 static_hints[0] =
'\0';
359 static_hints[1] =
'\0';
366 char *cp, *cpnext, *eqpos, *found;
370 if (init_env && *init_env !=
'\0') {
373 for (cp = init_env; cp != NULL; cp = cpnext) {
375 len = strlen(cp) + 1;
378 "WARNING: too long kenv string, ignoring %s\n",
382 eqpos = strchr(cp,
'=');
385 "WARNING: malformed static env value, ignoring %s\n",
403 "WARNING: too many kenv strings, ignoring %s\n",
409 strcpy(
kenvp[i++], cp);
411#ifdef PRESERVE_EARLY_KENV
414 explicit_bzero(cp, len - 1);
433 kenv_zone = uma_zcreate(
"kenv", size, NULL, NULL, NULL, NULL,
442 kenvp[dynamic_envpos] = NULL;
444 mtx_init(&
kenv_lock,
"kernel environment", NULL, MTX_DEF);
454 explicit_bzero(env, strlen(env));
469 for (cp =
kenvp[0], i = 0; cp != NULL; cp =
kenvp[++i]) {
470 if ((strncmp(cp,
name, len) == 0) &&
474 return (cp + len + 1);
495 for (ep = cp; (*ep !=
'=') && (*ep != 0); ep++)
501 if (!strncmp(
name, cp, len) &&
name[len] == 0)
535 ret = uma_zalloc(
kenv_zone, M_WAITOK | M_ZERO);
539 strlcpy(ret, cp, len);
598 char *
buf, *cp, *oldenv;
599 int namelen, vallen, i;
606 namelen = strlen(
name) + 1;
607 if (namelen > KENV_MNAMELEN + 1)
609 vallen = strlen(
value) + 1;
612 buf =
malloc(namelen + vallen, M_KENV, M_WAITOK);
621 free(oldenv, M_KENV);
624 for (i = 0; (cp =
kenvp[i]) != NULL; i++)
656 for (j = i + 1;
kenvp[j] != NULL; j++)
660 zfree(oldenv, M_KENV);
708 strlcpy(
data, cp, size);
720 int type_size,
bool allow_signed)
742 for (ptr =
buf; *ptr != 0; ) {
743 value = strtoq(ptr, &end, 0);
746 if (
value < 0 && !allow_signed)
787 while (*end ==
'\t' || *end ==
',' || *end ==
' ')
798 if ((
value >> shift) != old)
809 if (value < SCHAR_MIN || value > SCHAR_MAX)
812 if (value < 0 || value > UCHAR_MAX)
815 ((uint8_t *)pdata)[n] = (uint8_t)
value;
819 if (value < SHRT_MIN || value > SHRT_MAX)
822 if (value < 0 || value > USHRT_MAX)
825 ((uint16_t *)pdata)[n] = (uint16_t)
value;
829 if (value < INT_MIN || value > INT_MAX)
832 if (
value > UINT_MAX)
835 ((uint32_t *)pdata)[n] = (uint32_t)
value;
838 ((uint64_t *)pdata)[n] = (uint64_t)
value;
845 *psize = n * type_size;
880 *
data = (
unsigned int) tmp;
895 *
data = (int64_t) tmp;
910 *
data = (uint64_t) tmp;
940 *
data = (
unsigned long) tmp;
958 iv = strtoq(
value, &vtp, 0);
959 if (vtp ==
value || (vtp[0] !=
'\0' && vtp[1] !=
'\0')) {
1005 if ((strcmp(val,
"1") == 0) || (strcasecmp(val,
"true") == 0)) {
1008 }
else if ((strcmp(val,
"0") == 0) || (strcasecmp(val,
"false") == 0)) {
1013 printf(
"Environment variable %s has non-boolean value \"%s\"\n",
1068 struct tunable_int *d = (
struct tunable_int *)
data;
1070 TUNABLE_INT_FETCH(d->path, d->var);
1076 struct tunable_long *d = (
struct tunable_long *)
data;
1078 TUNABLE_LONG_FETCH(d->path, d->var);
1084 struct tunable_ulong *d = (
struct tunable_ulong *)
data;
1086 TUNABLE_ULONG_FETCH(d->path, d->var);
1092 struct tunable_int64 *d = (
struct tunable_int64 *)
data;
1094 TUNABLE_INT64_FETCH(d->path, d->var);
1100 struct tunable_uint64 *d = (
struct tunable_uint64 *)
data;
1102 TUNABLE_UINT64_FETCH(d->path, d->var);
1108 struct tunable_quad *d = (
struct tunable_quad *)
data;
1110 TUNABLE_QUAD_FETCH(d->path, d->var);
1116 struct tunable_bool *d = (
struct tunable_bool *)
data;
1118 TUNABLE_BOOL_FETCH(d->path, d->var);
1124 struct tunable_str *d = (
struct tunable_str *)
data;
1126 TUNABLE_STR_FETCH(d->path, d->var, d->size);
int getenv_bool(const char *name, bool *data)
int getenv_array(const char *name, void *pdata, int size, int *psize, int type_size, bool allow_signed)
void init_static_kenv(char *buf, size_t len)
void tunable_quad_init(void *data)
static void init_dynamic_kenv_from(char *init_env, int *curpos)
static void init_dynamic_kenv(void *data __unused)
int getenv_ulong(const char *name, unsigned long *data)
bool getenv_is_true(const char *name)
SYSINIT(kenv, SI_SUB_KMEM+1, SI_ORDER_FIRST, init_dynamic_kenv, NULL)
int getenv_long(const char *name, long *data)
static char * _getenv_dynamic_locked(const char *name, int *idx)
static char * kenv_acquire(const char *name)
char * kern_getenv(const char *name)
static void kenv_release(const char *buf)
int testenv(const char *name)
void tunable_ulong_init(void *data)
int getenv_string(const char *name, char *data, int size)
static char * kernenv_next(char *)
int kern_setenv(const char *name, const char *value)
static char * _getenv_dynamic(const char *name, int *idx)
static char * _getenv_static(const char *name)
void tunable_bool_init(void *data)
int getenv_quad(const char *name, quad_t *data)
int getenv_int(const char *name, int *data)
void tunable_int_init(void *data)
int getenv_uint64(const char *name, uint64_t *data)
static MALLOC_DEFINE(M_KENV, "kenv", "kernel environment")
int getenv_int64(const char *name, int64_t *data)
static int setenv_static(const char *name, const char *value)
static uma_zone_t kenv_zone
static char * _getenv_static_from(char *chkenv, const char *name)
bool getenv_is_false(const char *name)
void tunable_long_init(void *data)
int kern_unsetenv(const char *name)
void tunable_str_init(void *data)
int sys_kenv(struct thread *td, struct kenv_args *uap)
void tunable_uint64_init(void *data)
static int kenv_dump(struct thread *td, char **envp, int what, char *value, int len)
void tunable_int64_init(void *data)
int getenv_uint(const char *name, unsigned int *data)
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void zfree(void *addr, struct malloc_type *mtp)
void free(void *addr, struct malloc_type *mtp)
int priv_check(struct thread *td, int priv)
int printf(const char *fmt,...)
int sprintf(char *buf, const char *cfmt,...)