The branch main has been updated by asomers:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=874385b03f8d75111b98a6d6c0fbfb5ac5b29ace

commit 874385b03f8d75111b98a6d6c0fbfb5ac5b29ace
Author:     Alan Somers <asom...@freebsd.org>
AuthorDate: 2025-07-03 19:38:07 +0000
Commit:     Alan Somers <asom...@freebsd.org>
CommitDate: 2025-07-15 20:43:52 +0000

    uexterr_gettext: add tests
    
    Add tests for the new extended errno feature.
    
    Sponsored by:   ConnectWise
    MFC after:      2 weeks
    Reviewed by:    kib
    Differential Revision: https://reviews.freebsd.org/D51184
---
 sys/kern/sys_generic.c       |   6 +++
 sys/sys/exterrvar.h          |   1 +
 tests/sys/kern/Makefile      |   1 +
 tests/sys/kern/exterr_test.c | 108 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 116 insertions(+)

diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index 94e44d888181..b472aaea89e6 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -2309,6 +2309,12 @@ sys_exterrctl(struct thread *td, struct exterrctl_args 
*uap)
                        return (EINVAL);
                td->td_pflags2 &= ~TDP2_UEXTERR;
                return (0);
+       case EXTERRCTL_UD:
+               /*
+                * Important: this code must always return EINVAL and never any
+                * extended error, for testing purposes.
+                */
+               /* FALLTHROUGH */
        default:
                return (EINVAL);
        }
diff --git a/sys/sys/exterrvar.h b/sys/sys/exterrvar.h
index 15557c614f88..7bf1d264ff5e 100644
--- a/sys/sys/exterrvar.h
+++ b/sys/sys/exterrvar.h
@@ -21,6 +21,7 @@
 
 #define        EXTERRCTL_ENABLE        1
 #define        EXTERRCTL_DISABLE       2
+#define        EXTERRCTL_UD            3
 
 #define        EXTERRCTLF_FORCE        0x00000001
 
diff --git a/tests/sys/kern/Makefile b/tests/sys/kern/Makefile
index f2c24ad9dec9..336e73f29835 100644
--- a/tests/sys/kern/Makefile
+++ b/tests/sys/kern/Makefile
@@ -17,6 +17,7 @@ ATF_TESTS_C+= kern_copyin
 ATF_TESTS_C+=  kern_descrip_test
 # One test modifies the maxfiles limit, which can cause spurious test failures.
 TEST_METADATA.kern_descrip_test+= is_exclusive="true"
+ATF_TESTS_C+=  exterr_test
 ATF_TESTS_C+=  fdgrowtable_test
 ATF_TESTS_C+=  getdirentries_test
 ATF_TESTS_C+=  jail_lookup_root
diff --git a/tests/sys/kern/exterr_test.c b/tests/sys/kern/exterr_test.c
new file mode 100644
index 000000000000..17c84c1f8ed4
--- /dev/null
+++ b/tests/sys/kern/exterr_test.c
@@ -0,0 +1,108 @@
+/*-
+ * Copyright (C) 2025 ConnectWise, LLC. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/exterrvar.h>
+#include <sys/mman.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <exterr.h>
+#include <stdio.h>
+
+ATF_TC(gettext_extended);
+ATF_TC_HEAD(gettext_extended, tc)
+{
+       atf_tc_set_md_var(tc, "descr", "Retrieve an extended error message");
+}
+ATF_TC_BODY(gettext_extended, tc)
+{
+       char exterr[UEXTERROR_MAXLEN];
+       int r;
+
+       /*
+        * Use an invalid call to mmap() because it supports extended error
+        * messages, requires no special resources, and does not need root.
+        */
+       ATF_CHECK_ERRNO(ENOTSUP,
+           mmap(NULL, 0, PROT_MAX(PROT_READ) | PROT_WRITE, 0, -1, 0));
+       r = uexterr_gettext(exterr, sizeof(exterr));
+       ATF_CHECK_EQ(0, r);
+       printf("Extended error: %s\n", exterr);
+       /* Note: error string may need to be updated due to kernel changes */
+       ATF_CHECK(strstr(exterr, "prot is not subset of max_prot") != 0);
+}
+
+ATF_TC(gettext_noextended);
+ATF_TC_HEAD(gettext_noextended, tc)
+{
+       atf_tc_set_md_var(tc, "descr",
+           "Fail to retrieve an extended error message because none exists");
+}
+ATF_TC_BODY(gettext_noextended, tc)
+{
+       char exterr[UEXTERROR_MAXLEN];
+       int r;
+
+       ATF_CHECK_ERRNO(EINVAL, exterrctl(EXTERRCTL_UD, 0, NULL));
+       r = uexterr_gettext(exterr, sizeof(exterr));
+       ATF_CHECK_EQ(0, r);
+       ATF_CHECK_STREQ(exterr, "");
+}
+
+ATF_TC(gettext_noextended_after_extended);
+ATF_TC_HEAD(gettext_noextended_after_extended, tc)
+{
+       atf_tc_set_md_var(tc, "descr",
+           "uexterr_gettext should not return a stale extended error message");
+}
+ATF_TC_BODY(gettext_noextended_after_extended, tc)
+{
+       char exterr[UEXTERROR_MAXLEN];
+       int r;
+
+       /*
+        * First do something that will create an extended error message, but
+        * ignore it.
+        */
+       ATF_CHECK_ERRNO(ENOTSUP,
+           mmap(NULL, 0, PROT_MAX(PROT_READ) | PROT_WRITE, 0, -1, 0));
+
+       /* Then do something that won't create an extended error message */
+       ATF_CHECK_ERRNO(EINVAL, exterrctl(EXTERRCTL_UD, 0, NULL));
+
+       /* Hopefully we won't see the stale extended error message */
+       r = uexterr_gettext(exterr, sizeof(exterr));
+       ATF_CHECK_EQ(0, r);
+       ATF_CHECK_STREQ(exterr, "");
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+       ATF_TP_ADD_TC(tp, gettext_extended);
+       ATF_TP_ADD_TC(tp, gettext_noextended);
+       ATF_TP_ADD_TC(tp, gettext_noextended_after_extended);
+
+       return (atf_no_error());
+}

Reply via email to