1*874385b0SAlan Somers /*-
2*874385b0SAlan Somers * Copyright (C) 2025 ConnectWise, LLC. All rights reserved.
3*874385b0SAlan Somers *
4*874385b0SAlan Somers * Redistribution and use in source and binary forms, with or without
5*874385b0SAlan Somers * modification, are permitted provided that the following conditions
6*874385b0SAlan Somers * are met:
7*874385b0SAlan Somers * 1. Redistributions of source code must retain the above copyright
8*874385b0SAlan Somers * notice, this list of conditions and the following disclaimer.
9*874385b0SAlan Somers * 2. Redistributions in binary form must reproduce the above copyright
10*874385b0SAlan Somers * notice, this list of conditions and the following disclaimer in the
11*874385b0SAlan Somers * documentation and/or other materials provided with the distribution.
12*874385b0SAlan Somers *
13*874385b0SAlan Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14*874385b0SAlan Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15*874385b0SAlan Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16*874385b0SAlan Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17*874385b0SAlan Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18*874385b0SAlan Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19*874385b0SAlan Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20*874385b0SAlan Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21*874385b0SAlan Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22*874385b0SAlan Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23*874385b0SAlan Somers * SUCH DAMAGE.
24*874385b0SAlan Somers */
25*874385b0SAlan Somers
26*874385b0SAlan Somers #include <sys/exterrvar.h>
27*874385b0SAlan Somers #include <sys/mman.h>
28*874385b0SAlan Somers
29*874385b0SAlan Somers #include <atf-c.h>
30*874385b0SAlan Somers #include <errno.h>
31*874385b0SAlan Somers #include <exterr.h>
32*874385b0SAlan Somers #include <stdio.h>
33*874385b0SAlan Somers
34*874385b0SAlan Somers ATF_TC(gettext_extended);
ATF_TC_HEAD(gettext_extended,tc)35*874385b0SAlan Somers ATF_TC_HEAD(gettext_extended, tc)
36*874385b0SAlan Somers {
37*874385b0SAlan Somers atf_tc_set_md_var(tc, "descr", "Retrieve an extended error message");
38*874385b0SAlan Somers }
ATF_TC_BODY(gettext_extended,tc)39*874385b0SAlan Somers ATF_TC_BODY(gettext_extended, tc)
40*874385b0SAlan Somers {
41*874385b0SAlan Somers char exterr[UEXTERROR_MAXLEN];
42*874385b0SAlan Somers int r;
43*874385b0SAlan Somers
44*874385b0SAlan Somers /*
45*874385b0SAlan Somers * Use an invalid call to mmap() because it supports extended error
46*874385b0SAlan Somers * messages, requires no special resources, and does not need root.
47*874385b0SAlan Somers */
48*874385b0SAlan Somers ATF_CHECK_ERRNO(ENOTSUP,
49*874385b0SAlan Somers mmap(NULL, 0, PROT_MAX(PROT_READ) | PROT_WRITE, 0, -1, 0));
50*874385b0SAlan Somers r = uexterr_gettext(exterr, sizeof(exterr));
51*874385b0SAlan Somers ATF_CHECK_EQ(0, r);
52*874385b0SAlan Somers printf("Extended error: %s\n", exterr);
53*874385b0SAlan Somers /* Note: error string may need to be updated due to kernel changes */
54*874385b0SAlan Somers ATF_CHECK(strstr(exterr, "prot is not subset of max_prot") != 0);
55*874385b0SAlan Somers }
56*874385b0SAlan Somers
57*874385b0SAlan Somers ATF_TC(gettext_noextended);
ATF_TC_HEAD(gettext_noextended,tc)58*874385b0SAlan Somers ATF_TC_HEAD(gettext_noextended, tc)
59*874385b0SAlan Somers {
60*874385b0SAlan Somers atf_tc_set_md_var(tc, "descr",
61*874385b0SAlan Somers "Fail to retrieve an extended error message because none exists");
62*874385b0SAlan Somers }
ATF_TC_BODY(gettext_noextended,tc)63*874385b0SAlan Somers ATF_TC_BODY(gettext_noextended, tc)
64*874385b0SAlan Somers {
65*874385b0SAlan Somers char exterr[UEXTERROR_MAXLEN];
66*874385b0SAlan Somers int r;
67*874385b0SAlan Somers
68*874385b0SAlan Somers ATF_CHECK_ERRNO(EINVAL, exterrctl(EXTERRCTL_UD, 0, NULL));
69*874385b0SAlan Somers r = uexterr_gettext(exterr, sizeof(exterr));
70*874385b0SAlan Somers ATF_CHECK_EQ(0, r);
71*874385b0SAlan Somers ATF_CHECK_STREQ(exterr, "");
72*874385b0SAlan Somers }
73*874385b0SAlan Somers
74*874385b0SAlan Somers ATF_TC(gettext_noextended_after_extended);
ATF_TC_HEAD(gettext_noextended_after_extended,tc)75*874385b0SAlan Somers ATF_TC_HEAD(gettext_noextended_after_extended, tc)
76*874385b0SAlan Somers {
77*874385b0SAlan Somers atf_tc_set_md_var(tc, "descr",
78*874385b0SAlan Somers "uexterr_gettext should not return a stale extended error message");
79*874385b0SAlan Somers }
ATF_TC_BODY(gettext_noextended_after_extended,tc)80*874385b0SAlan Somers ATF_TC_BODY(gettext_noextended_after_extended, tc)
81*874385b0SAlan Somers {
82*874385b0SAlan Somers char exterr[UEXTERROR_MAXLEN];
83*874385b0SAlan Somers int r;
84*874385b0SAlan Somers
85*874385b0SAlan Somers /*
86*874385b0SAlan Somers * First do something that will create an extended error message, but
87*874385b0SAlan Somers * ignore it.
88*874385b0SAlan Somers */
89*874385b0SAlan Somers ATF_CHECK_ERRNO(ENOTSUP,
90*874385b0SAlan Somers mmap(NULL, 0, PROT_MAX(PROT_READ) | PROT_WRITE, 0, -1, 0));
91*874385b0SAlan Somers
92*874385b0SAlan Somers /* Then do something that won't create an extended error message */
93*874385b0SAlan Somers ATF_CHECK_ERRNO(EINVAL, exterrctl(EXTERRCTL_UD, 0, NULL));
94*874385b0SAlan Somers
95*874385b0SAlan Somers /* Hopefully we won't see the stale extended error message */
96*874385b0SAlan Somers r = uexterr_gettext(exterr, sizeof(exterr));
97*874385b0SAlan Somers ATF_CHECK_EQ(0, r);
98*874385b0SAlan Somers ATF_CHECK_STREQ(exterr, "");
99*874385b0SAlan Somers }
100*874385b0SAlan Somers
ATF_TP_ADD_TCS(tp)101*874385b0SAlan Somers ATF_TP_ADD_TCS(tp)
102*874385b0SAlan Somers {
103*874385b0SAlan Somers ATF_TP_ADD_TC(tp, gettext_extended);
104*874385b0SAlan Somers ATF_TP_ADD_TC(tp, gettext_noextended);
105*874385b0SAlan Somers ATF_TP_ADD_TC(tp, gettext_noextended_after_extended);
106*874385b0SAlan Somers
107*874385b0SAlan Somers return (atf_no_error());
108*874385b0SAlan Somers }
109