Page MenuHomeFreeBSD

D30835.id91152.diff
No OneTemporary

D30835.id91152.diff

Index: bin/kenv/kenv.1
===================================================================
--- bin/kenv/kenv.1
+++ bin/kenv/kenv.1
@@ -32,6 +32,7 @@
.Nd list or modify the kernel environment
.Sh SYNOPSIS
.Nm
+.Op Fl l | s
.Op Fl hNq
.Nm
.Op Fl qv
@@ -45,6 +46,23 @@
.Nm
utility will list all variables in the kernel environment if
invoked without arguments.
+.Pp
+If the
+.Fl l
+option is specified, then the static environment provided by
+.Xr loader 8
+will be listed instead.
+Similarly, the
+.Fl s
+option will list the static environment defined by the kernel config.
+Both of the
+.Fl l
+and
+.Fl s
+options are dependent on the kernel being configured to preserve early kernel
+environments.
+The default kernel configuration does not preserve these environments.
+.Pp
If the
.Fl h
option is specified, it will limit the report to kernel probe hints.
Index: bin/kenv/kenv.c
===================================================================
--- bin/kenv/kenv.c
+++ bin/kenv/kenv.c
@@ -29,6 +29,7 @@
#include <sys/types.h>
#include <sys/sysctl.h>
#include <err.h>
+#include <errno.h>
#include <kenv.h>
#include <stdio.h>
#include <stdlib.h>
@@ -36,14 +37,16 @@
#include <unistd.h>
static void usage(void);
-static int kdumpenv(void);
+static int kdumpenv(int dump_type);
static int kgetenv(const char *);
static int ksetenv(const char *, char *);
static int kunsetenv(const char *);
static int hflag = 0;
+static int lflag = 0;
static int Nflag = 0;
static int qflag = 0;
+static int sflag = 0;
static int uflag = 0;
static int vflag = 0;
@@ -51,7 +54,7 @@
usage(void)
{
(void)fprintf(stderr, "%s\n%s\n%s\n",
- "usage: kenv [-hNq]",
+ "usage: kenv [-l|-s] [-hNq]",
" kenv [-qv] variable[=value]",
" kenv [-q] -u variable");
exit(1);
@@ -65,17 +68,23 @@
val = NULL;
env = NULL;
- while ((ch = getopt(argc, argv, "hNquv")) != -1) {
+ while ((ch = getopt(argc, argv, "hlNqsuv")) != -1) {
switch (ch) {
case 'h':
hflag++;
break;
+ case 'l':
+ lflag++;
+ break;
case 'N':
Nflag++;
break;
case 'q':
qflag++;
break;
+ case 's':
+ sflag++;
+ break;
case 'u':
uflag++;
break;
@@ -100,12 +109,23 @@
}
if ((hflag || Nflag) && env != NULL)
usage();
+ if (lflag && sflag)
+ usage();
if (argc > 0 || ((uflag || vflag) && env == NULL))
usage();
if (env == NULL) {
- error = kdumpenv();
- if (error && !qflag)
- warn("kdumpenv");
+ if (lflag)
+ error = kdumpenv(KENV_DUMP_LOADER);
+ else if (sflag)
+ error = kdumpenv(KENV_DUMP_STATIC);
+ else
+ error = kdumpenv(KENV_DUMP);
+ if (error && !qflag) {
+ if (errno == ENOENT)
+ warnx("requested environment is unavailable");
+ else
+ warn("kdumpenv");
+ }
} else if (val == NULL) {
if (uflag) {
error = kunsetenv(env);
@@ -125,12 +145,12 @@
}
static int
-kdumpenv(void)
+kdumpenv(int dump_type)
{
char *buf, *bp, *cp;
int buflen, envlen;
- envlen = kenv(KENV_DUMP, NULL, NULL, 0);
+ envlen = kenv(dump_type, NULL, NULL, 0);
if (envlen < 0)
return (-1);
for (;;) {
@@ -138,7 +158,7 @@
buf = calloc(1, buflen + 1);
if (buf == NULL)
return (-1);
- envlen = kenv(KENV_DUMP, NULL, buf, buflen);
+ envlen = kenv(dump_type, NULL, buf, buflen);
if (envlen < 0) {
free(buf);
return (-1);
Index: lib/libc/sys/kenv.2
===================================================================
--- lib/libc/sys/kenv.2
+++ lib/libc/sys/kenv.2
@@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 20, 2017
+.Dd June 20, 2021
.Dt KENV 2
.Os
.Sh NAME
@@ -49,7 +49,7 @@
The
.Fa action
argument can be one of the following:
-.Bl -tag -width ".Dv KENV_UNSET"
+.Bl -tag -width ".Dv KENV_DUMP_LOADER"
.It Dv KENV_GET
Get the
.Fa value
@@ -90,7 +90,7 @@
arguments are ignored.
This option is only available to the superuser.
.It Dv KENV_DUMP
-Dump as much of the kernel environment as will fit in
+Dump as much of the dynamic kernel environment as will fit in
.Fa value ,
whose size is given in
.Fa len .
@@ -103,6 +103,18 @@
The
.Fa name
is ignored.
+.It Dv KENV_DUMP_LOADER
+Dump the static environment provided by
+.Xr loader 8 ,
+with semantics identical to
+.Dv KENV_DUMP .
+Duplicate and malformed variables originally present in this environment are
+discarded by the kernel and will not appear in the output.
+.It Dv KENV_DUMP_STATIC
+Dump the static environment defined by the kernel
+.Xr config 5 .
+The semantics are identical to
+.Dv KENV_DUMP_LOADER .
.El
.Sh RETURN VALUES
The
@@ -142,6 +154,12 @@
.Dv KENV_GET
or
.Dv KENV_UNSET .
+.It Bq Er ENOENT
+The requested environment is not available for a
+.Dv KENV_DUMP_LOADER
+or
+.Dv KENV_DUMP_STATIC .
+The kernel is configured to destroy these environments by default.
.It Bq Er EPERM
A user other than the superuser attempted to set or unset a kernel
environment variable.
Index: sys/kern/kern_environment.c
===================================================================
--- sys/kern/kern_environment.c
+++ sys/kern/kern_environment.c
@@ -95,28 +95,46 @@
panic("%s: called before SI_SUB_KMEM", __func__)
int
-sys_kenv(td, uap)
- struct thread *td;
- struct kenv_args /* {
- int what;
- const char *name;
- char *value;
- int len;
- } */ *uap;
+sys_kenv(struct thread *td, struct kenv_args *uap)
{
- char *name, *value, *buffer = NULL;
+ char *name, *value, **envp, *senv, *buffer = NULL;
size_t len, done, needed, buflen;
- int error, i;
+ int error;
KASSERT(dynamic_kenv, ("kenv: dynamic_kenv = false"));
error = 0;
- if (uap->what == KENV_DUMP) {
+ if (uap->what == KENV_DUMP || uap->what == KENV_DUMP_LOADER ||
+ uap->what == KENV_DUMP_STATIC) {
#ifdef MAC
error = mac_kenv_check_dump(td->td_ucred);
if (error)
return (error);
#endif
+#ifndef PRESERVE_EARLY_KENV
+ if (uap->what == KENV_DUMP_LOADER ||
+ uap->what == KENV_DUMP_STATIC)
+ return (ENOENT);
+#endif
+ /* Select the appropriate env pointer for what we wish to dump. */
+ if (uap->what == KENV_DUMP) {
+ envp = kenvp;
+ } else {
+ envp = &senv;
+ if (uap->what == KENV_DUMP_LOADER)
+ senv = md_envp;
+ else if (uap->what == KENV_DUMP_STATIC)
+ senv = kern_envp;
+ else
+ senv = NULL;
+ /*
+ * Partially implemented dump type; userland triggered
+ * it, but we shouldn't get here unless it's been
+ * recognized above.
+ */
+ MPASS(senv != NULL);
+ }
+
done = needed = 0;
buflen = uap->len;
if (buflen > KENV_SIZE * (KENV_MNAMELEN + kenv_mvallen + 2))
@@ -124,9 +142,12 @@
kenv_mvallen + 2);
if (uap->len > 0 && uap->value != NULL)
buffer = malloc(buflen, M_TEMP, M_WAITOK|M_ZERO);
- mtx_lock(&kenv_lock);
- for (i = 0; kenvp[i] != NULL; i++) {
- len = strlen(kenvp[i]) + 1;
+
+ /* Only take the lock for the dynamic kenv. */
+ if (uap->what == KENV_DUMP)
+ mtx_lock(&kenv_lock);
+ while (*envp != NULL) {
+ len = strlen(*envp) + 1;
needed += len;
len = min(len, buflen - done);
/*
@@ -134,11 +155,18 @@
* buffer, just keep computing the required size.
*/
if (uap->value != NULL && buffer != NULL && len > 0) {
- bcopy(kenvp[i], buffer + done, len);
+ bcopy(*envp, buffer + done, len);
done += len;
}
+
+ /* Advance the pointer depending on the kenv format. */
+ if (uap->what == KENV_DUMP)
+ envp++;
+ else
+ senv = kernenv_next(senv);
}
- mtx_unlock(&kenv_lock);
+ if (uap->what == KENV_DUMP)
+ mtx_unlock(&kenv_lock);
if (buffer != NULL) {
error = copyout(buffer, uap->value, done);
free(buffer, M_TEMP);
Index: sys/sys/kenv.h
===================================================================
--- sys/sys/kenv.h
+++ sys/sys/kenv.h
@@ -34,10 +34,12 @@
/*
* Constants for the kenv(2) syscall
*/
-#define KENV_GET 0
-#define KENV_SET 1
-#define KENV_UNSET 2
-#define KENV_DUMP 3
+#define KENV_GET 0
+#define KENV_SET 1
+#define KENV_UNSET 2
+#define KENV_DUMP 3
+#define KENV_DUMP_LOADER 4
+#define KENV_DUMP_STATIC 5
#define KENV_MNAMELEN 128 /* Maximum name length (for the syscall) */
#define KENV_MVALLEN 128 /* Maximum value length (for the syscall) */

File Metadata

Mime Type
text/plain
Expires
Fri, Mar 27, 8:11 PM (4 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30442627
Default Alt Text
D30835.id91152.diff (7 KB)

Event Timeline