The branch main has been updated by kevans:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=4fd518fcb2bbee4c8c41215d6993b923ef57a0e5

commit 4fd518fcb2bbee4c8c41215d6993b923ef57a0e5
Author:     Kyle Evans <[email protected]>
AuthorDate: 2026-06-22 20:22:25 +0000
Commit:     Kyle Evans <[email protected]>
CommitDate: 2026-06-22 20:22:25 +0000

    kern: add a security knob to disable unprivileged access to kenv
    
    We sometimes store sensitive things in the kenv that get zapped, but we
    really shouldn't rely on that zapping to actually happen.  Most
    unprivileged processes don't really need to read from the kernel
    environment in the first place, so add a knob that allows it to be
    disabled.
    
    Note that we consider jailed root to be unprivileged from this
    perspective; they have their own meta/env concepts and we should
    encourage users to take advantage of those for passing information to
    jails.
    
    "Hey we should do something about that":        dch
    Reviewed by:    imp, ziaee, zlei (all slightly previous version)
    Differential Revision:  https://reviews.freebsd.org/D57697
---
 bin/kenv/kenv.1             | 10 +++++++++-
 lib/libsys/kenv.2           |  7 ++++++-
 share/man/man7/security.7   |  4 +++-
 sys/kern/kern_environment.c | 46 +++++++++++++++++++++++++++++++++++++++------
 sys/sys/priv.h              |  1 +
 5 files changed, 59 insertions(+), 9 deletions(-)

diff --git a/bin/kenv/kenv.1 b/bin/kenv/kenv.1
index 9b6d0e0b33f2..c0cf0c29cabe 100644
--- a/bin/kenv/kenv.1
+++ b/bin/kenv/kenv.1
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd June 20, 2021
+.Dd June 22, 2026
 .Dt KENV 1
 .Os
 .Sh NAME
@@ -166,3 +166,11 @@ The
 .Nm
 utility appeared in
 .Fx 4.1.1 .
+.Sh SECURITY CONSIDERATIONS
+Note that unprivileged users are allowed to read from the kernel environment,
+unless the
+.Va security.bsd.unprivileged_kenv_read
+sysctl is set to 0.
+This includes both listing the kernel environment, as well as getting a 
specific
+.Va variable
+from the environment.
diff --git a/lib/libsys/kenv.2 b/lib/libsys/kenv.2
index 9f179ff2faa6..bdf4dd7f1386 100644
--- a/lib/libsys/kenv.2
+++ b/lib/libsys/kenv.2
@@ -24,7 +24,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 .\" DAMAGE.
 .\"
-.Dd June 20, 2021
+.Dd June 22, 2026
 .Dt KENV 2
 .Os
 .Sh NAME
@@ -161,6 +161,11 @@ 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.
+.It Bq Er EPERM
+A user other than the superuser attempted to get a variable from or dump the
+kernel environment, and the
+.Va security.bsd.unprivileged_kenv_read
+sysctl is set to 0.
 .It Bq Er EFAULT
 A bad address was encountered while attempting to copy in user arguments
 or copy out value(s).
diff --git a/share/man/man7/security.7 b/share/man/man7/security.7
index 395cf082c2fc..bec5c4f0b001 100644
--- a/share/man/man7/security.7
+++ b/share/man/man7/security.7
@@ -26,7 +26,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd March 22, 2026
+.Dd June 22, 2026
 .Dt SECURITY 7
 .Os
 .Sh NAME
@@ -987,6 +987,8 @@ and usual termination signals like
 and
 .Dv SIGTERM ,
 to the processes executing programs with changed uids.
+.It Va security.bsd.unprivileged_kenv_read
+Controls availability of kernel environment variables to non-root users.
 .It Va security.bsd.unprivileged_proc_debug
 Controls availability of the process debugging facilities to non-root users.
 See also
diff --git a/sys/kern/kern_environment.c b/sys/kern/kern_environment.c
index 7c0654769581..72c7544b4bac 100644
--- a/sys/kern/kern_environment.c
+++ b/sys/kern/kern_environment.c
@@ -49,6 +49,7 @@
 #include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/queue.h>
+#include <sys/sysctl.h>
 #include <sys/sysent.h>
 #include <sys/sysproto.h>
 
@@ -91,6 +92,11 @@ bool dynamic_kenv;
 #define KENV_CHECK     if (!dynamic_kenv) \
                            panic("%s: called before SI_SUB_KMEM", __func__)
 
+static int unprivileged_kenv_read = 1;
+SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_kenv_read, CTLFLAG_RW,
+    &unprivileged_kenv_read, 1,
+    "Unprivileged processes can read the kernel environment");
+
 static int
 kenv_dump(struct thread *td, char **envp, int what, char *value, int len)
 {
@@ -155,6 +161,33 @@ kenv_dump(struct thread *td, char **envp, int what, char 
*value, int len)
        return (error);
 }
 
+static int
+kenv_read_allowed(struct thread *td, int which)
+{
+       int error;
+
+       if (!unprivileged_kenv_read) {
+               error = priv_check(td, PRIV_KENV_READ);
+               if (error)
+                       return (error);
+       }
+
+       switch (which) {
+       case KENV_DUMP:
+       case KENV_DUMP_LOADER:
+       case KENV_DUMP_STATIC:
+#ifdef MAC
+               error = mac_kenv_check_dump(td->td_ucred);
+#endif
+               break;
+       default:
+               error = 0;
+               break;
+       }
+
+       return (error);
+}
+
 int
 sys_kenv(struct thread *td, struct kenv_args *uap)
 {
@@ -168,19 +201,15 @@ sys_kenv(struct thread *td, struct kenv_args *uap)
 
        switch (uap->what) {
        case KENV_DUMP:
-#ifdef MAC
-               error = mac_kenv_check_dump(td->td_ucred);
+               error = kenv_read_allowed(td, uap->what);
                if (error)
                        return (error);
-#endif
                return (kenv_dump(td, kenvp, uap->what, uap->value, uap->len));
        case KENV_DUMP_LOADER:
        case KENV_DUMP_STATIC:
-#ifdef MAC
-               error = mac_kenv_check_dump(td->td_ucred);
+               error = kenv_read_allowed(td, uap->what);
                if (error)
                        return (error);
-#endif
 #ifdef PRESERVE_EARLY_KENV
                return (kenv_dump(td,
                    uap->what == KENV_DUMP_LOADER ? (char **)md_envp :
@@ -199,6 +228,11 @@ sys_kenv(struct thread *td, struct kenv_args *uap)
                if (error)
                        return (error);
                break;
+       case KENV_GET:
+               error = kenv_read_allowed(td, uap->what);
+               if (error)
+                       return (error);
+               break;
        }
 
        name = malloc(KENV_MNAMELEN + 1, M_TEMP, M_WAITOK);
diff --git a/sys/sys/priv.h b/sys/sys/priv.h
index 148f2191c6e0..87775632f8a8 100644
--- a/sys/sys/priv.h
+++ b/sys/sys/priv.h
@@ -141,6 +141,7 @@
  */
 #define        PRIV_KENV_SET           120     /* Set kernel env. variables. */
 #define        PRIV_KENV_UNSET         121     /* Unset kernel env. variables. 
*/
+#define        PRIV_KENV_READ          122     /* Get/dump kernel env. 
variables. */
 
 /*
  * Loadable kernel module privileges.

Reply via email to