The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=42210fe8dcd4684a45e0e4db1b8194e291dc8fda

commit 42210fe8dcd4684a45e0e4db1b8194e291dc8fda
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2025-12-28 00:23:27 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2025-12-29 01:16:25 +0000

    exterror: Add EXTERROR_VERBOSE env variable to control verbosity
    
    If the variable is set and the process is not suid, __uexterr_format(),
    used by err(3), prints errno/category/source line/pX always, not only
    when there is no kernel message provided.
    
    Requested by:   mckusick
    Reviewed by:    emaste, mckusick
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D54380
---
 lib/libc/gen/uexterr_format.c | 53 +++++++++++++++++++++++++++++++++++++++----
 1 file changed, 48 insertions(+), 5 deletions(-)

diff --git a/lib/libc/gen/uexterr_format.c b/lib/libc/gen/uexterr_format.c
index 68cd2abfe312..3321fd80616d 100644
--- a/lib/libc/gen/uexterr_format.c
+++ b/lib/libc/gen/uexterr_format.c
@@ -11,26 +11,69 @@
 #include <sys/types.h>
 #include <sys/exterrvar.h>
 #include <exterr.h>
+#include <stdbool.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
+
+static const char exterror_verbose_name[] = "EXTERROR_VERBOSE";
+enum exterr_verbose_state {
+       EXTERR_VERBOSE_UNKNOWN = 100,
+       EXTERR_VERBOSE_DEFAULT,
+       EXTERR_VERBOSE_ALLOW,
+};
+static enum exterr_verbose_state exterror_verbose = EXTERR_VERBOSE_UNKNOWN;
+
+static void
+exterr_verbose_init(void)
+{
+       /*
+        * No need to care about thread-safety, the result is
+        * idempotent.
+        */
+       if (exterror_verbose != EXTERR_VERBOSE_UNKNOWN)
+               return;
+       if (issetugid()) {
+               exterror_verbose = EXTERR_VERBOSE_DEFAULT;
+       } else if (getenv(exterror_verbose_name) != NULL) {
+               exterror_verbose = EXTERR_VERBOSE_ALLOW;
+       } else {
+               exterror_verbose = EXTERR_VERBOSE_DEFAULT;
+       }
+}
 
 int
 __uexterr_format(const struct uexterror *ue, char *buf, size_t bufsz)
 {
+       bool has_msg;
+
        if (bufsz > UEXTERROR_MAXLEN)
                bufsz = UEXTERROR_MAXLEN;
        if (ue->error == 0) {
                strlcpy(buf, "", bufsz);
                return (0);
        }
-       if (ue->msg[0] == '\0') {
-               snprintf(buf, bufsz,
+       exterr_verbose_init();
+       has_msg = ue->msg[0] != '\0';
+
+       if (has_msg) {
+               snprintf(buf, bufsz, ue->msg, (uintmax_t)ue->p1,
+                   (uintmax_t)ue->p2);
+       } else {
+               strlcpy(buf, "", bufsz);
+       }
+
+       if (exterror_verbose == EXTERR_VERBOSE_ALLOW || !has_msg) {
+               char lbuf[128];
+
+               snprintf(lbuf, sizeof(lbuf),
                    "errno %d category %u (src line %u) p1 %#jx p2 %#jx",
                    ue->error, ue->cat, ue->src_line,
                    (uintmax_t)ue->p1, (uintmax_t)ue->p2);
-       } else {
-               snprintf(buf, bufsz, ue->msg, (uintmax_t)ue->p1,
-                   (uintmax_t)ue->p2);
+               if (has_msg)
+                       strlcat(buf, " ", bufsz);
+               strlcat(buf, lbuf, bufsz);
        }
        return (0);
 }

Reply via email to