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); }
