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