11.1Sriastrad/* $NetBSD: setjmp_tester.c,v 1.1 2025/04/27 16:22:26 riastradh Exp $ */ 21.1Sriastrad 31.1Sriastrad/*- 41.1Sriastrad * Copyright (c) 2025 The NetBSD Foundation, Inc. 51.1Sriastrad * All rights reserved. 61.1Sriastrad * 71.1Sriastrad * Redistribution and use in source and binary forms, with or without 81.1Sriastrad * modification, are permitted provided that the following conditions 91.1Sriastrad * are met: 101.1Sriastrad * 1. Redistributions of source code must retain the above copyright 111.1Sriastrad * notice, this list of conditions and the following disclaimer. 121.1Sriastrad * 2. Redistributions in binary form must reproduce the above copyright 131.1Sriastrad * notice, this list of conditions and the following disclaimer in the 141.1Sriastrad * documentation and/or other materials provided with the distribution. 151.1Sriastrad * 161.1Sriastrad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 171.1Sriastrad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 181.1Sriastrad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 191.1Sriastrad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 201.1Sriastrad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 211.1Sriastrad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 221.1Sriastrad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 231.1Sriastrad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 241.1Sriastrad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 251.1Sriastrad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 261.1Sriastrad * POSSIBILITY OF SUCH DAMAGE. 271.1Sriastrad */ 281.1Sriastrad 291.1Sriastrad#include <sys/cdefs.h> 301.1Sriastrad__KERNEL_RCSID(0, "$NetBSD: setjmp_tester.c,v 1.1 2025/04/27 16:22:26 riastradh Exp $"); 311.1Sriastrad 321.1Sriastrad#include <sys/module.h> 331.1Sriastrad#include <sys/sysctl.h> 341.1Sriastrad#include <sys/systm.h> 351.1Sriastrad 361.1SriastradMODULE(MODULE_CLASS_MISC, setjmp_tester, NULL); 371.1Sriastrad 381.1Sriastradstatic struct sysctllog *setjmp_tester_sysctllog; 391.1Sriastradstatic const struct sysctlnode *setjmp_tester_sysctlnode; 401.1Sriastradstatic kmutex_t setjmp_tester_lock; 411.1Sriastradstatic bool setjmp_tester_done; 421.1Sriastradstatic label_t setjmp_tester_label; 431.1Sriastrad 441.1Sriastrad__noinline 451.1Sriastradstatic void 461.1Sriastradsetjmp_tester_subroutine(void) 471.1Sriastrad{ 481.1Sriastrad 491.1Sriastrad printf("%s: call longjmp\n", __func__); 501.1Sriastrad setjmp_tester_done = true; 511.1Sriastrad longjmp(&setjmp_tester_label); 521.1Sriastrad printf("%s: unreachable\n", __func__); 531.1Sriastrad} 541.1Sriastrad 551.1Sriastradstatic int 561.1Sriastradsetjmp_tester_test(void) 571.1Sriastrad{ 581.1Sriastrad int result; 591.1Sriastrad 601.1Sriastrad mutex_enter(&setjmp_tester_lock); 611.1Sriastrad 621.1Sriastrad setjmp_tester_done = false; 631.1Sriastrad result = setjmp(&setjmp_tester_label); 641.1Sriastrad if (!setjmp_tester_done) { 651.1Sriastrad printf("%s: setjmp returned %d at first\n", __func__, result); 661.1Sriastrad if (result != 0) { 671.1Sriastrad result = -1; 681.1Sriastrad goto out; 691.1Sriastrad } 701.1Sriastrad setjmp_tester_subroutine(); 711.1Sriastrad /*NOTREACHED*/ 721.1Sriastrad printf("%s: setjmp_tester_subroutine returned\n", __func__); 731.1Sriastrad result = -1; 741.1Sriastrad } else { 751.1Sriastrad printf("%s: setjmp returned %d at second\n", __func__, result); 761.1Sriastrad if (result == 0) { 771.1Sriastrad result = -2; 781.1Sriastrad goto out; 791.1Sriastrad } 801.1Sriastrad } 811.1Sriastrad 821.1Sriastradout: mutex_exit(&setjmp_tester_lock); 831.1Sriastrad return result; 841.1Sriastrad} 851.1Sriastrad 861.1Sriastradstatic int 871.1Sriastradsetjmp_tester_test_sysctl(SYSCTLFN_ARGS) 881.1Sriastrad{ 891.1Sriastrad struct sysctlnode node = *rnode; 901.1Sriastrad int v = 0; 911.1Sriastrad int error; 921.1Sriastrad 931.1Sriastrad if (newp == NULL) { 941.1Sriastrad error = ENOENT; 951.1Sriastrad goto out; 961.1Sriastrad } 971.1Sriastrad error = sysctl_copyin(curlwp, newp, &v, sizeof(v)); 981.1Sriastrad if (error) 991.1Sriastrad goto out; 1001.1Sriastrad switch (v) { 1011.1Sriastrad case 1: 1021.1Sriastrad v = setjmp_tester_test(); 1031.1Sriastrad break; 1041.1Sriastrad default: 1051.1Sriastrad error = EINVAL; 1061.1Sriastrad break; 1071.1Sriastrad } 1081.1Sriastrad node.sysctl_data = &v; 1091.1Sriastrad error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1101.1Sriastrad 1111.1Sriastradout: return error; 1121.1Sriastrad} 1131.1Sriastrad 1141.1Sriastradstatic int 1151.1Sriastradsetjmp_tester_modcmd(modcmd_t cmd, void *arg) 1161.1Sriastrad{ 1171.1Sriastrad int error = 0; 1181.1Sriastrad 1191.1Sriastrad switch (cmd) { 1201.1Sriastrad case MODULE_CMD_INIT: 1211.1Sriastrad mutex_init(&setjmp_tester_lock, MUTEX_DEFAULT, IPL_NONE); 1221.1Sriastrad error = sysctl_createv(&setjmp_tester_sysctllog, 0, 1231.1Sriastrad NULL, &setjmp_tester_sysctlnode, 1241.1Sriastrad CTLFLAG_PERMANENT, CTLTYPE_NODE, "setjmp_tester", 1251.1Sriastrad SYSCTL_DESCR("setjmp/longjmp testing interface"), 1261.1Sriastrad NULL, 0, NULL, 0, 1271.1Sriastrad CTL_KERN, CTL_CREATE, CTL_EOL); 1281.1Sriastrad if (error) 1291.1Sriastrad goto fini; 1301.1Sriastrad error = sysctl_createv(&setjmp_tester_sysctllog, 0, 1311.1Sriastrad &setjmp_tester_sysctlnode, NULL, 1321.1Sriastrad CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, "test", 1331.1Sriastrad SYSCTL_DESCR("setjmp/longjmp test trigger"), 1341.1Sriastrad &setjmp_tester_test_sysctl, 0, NULL, 0, 1351.1Sriastrad CTL_CREATE, CTL_EOL); 1361.1Sriastrad if (error) 1371.1Sriastrad goto fini; 1381.1Sriastrad return error; 1391.1Sriastrad case MODULE_CMD_FINI: 1401.1Sriastrad fini: 1411.1Sriastrad sysctl_teardown(&setjmp_tester_sysctllog); 1421.1Sriastrad mutex_destroy(&setjmp_tester_lock); 1431.1Sriastrad return error; 1441.1Sriastrad default: 1451.1Sriastrad return ENOTTY; 1461.1Sriastrad } 1471.1Sriastrad} 148