1 /* $NetBSD: h_segv.c,v 1.2 2017/12/08 14:40:45 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2017 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 #include <sys/cdefs.h> 32 __RCSID("$NetBSD: h_segv.c,v 1.2 2017/12/08 14:40:45 christos Exp $"); 33 34 #include <stdio.h> 35 #include <string.h> 36 #include <stdlib.h> 37 #include <unistd.h> 38 #include <signal.h> 39 #include <err.h> 40 41 // A faulting address 42 static int *p = (int *) 0xfefefef0; 43 44 static int flags; 45 #define F_RECURSE 1 46 #define F_HANDLE 2 47 #define F_MASK 4 48 49 static struct { 50 const char *n; 51 int v; 52 } nv[] = { 53 { "recurse", F_RECURSE }, 54 { "handle", F_HANDLE }, 55 { "mask", F_MASK }, 56 }; 57 58 static void 59 foo(int s) 60 { 61 char buf[64]; 62 int i = snprintf(buf, sizeof(buf), "got %d\n", s); 63 write(2, buf, i); 64 if (flags & F_RECURSE) 65 *p = 0; 66 exit(EXIT_SUCCESS); 67 } 68 69 static __dead void 70 usage(void) 71 { 72 fprintf(stderr, "Usage: %s recurse|mask|handle ...\n", getprogname()); 73 exit(EXIT_FAILURE); 74 } 75 76 int 77 main(int argc, char *argv[]) 78 { 79 if (argc == 1) 80 usage(); 81 82 for (int i = 1; i < argc; i++) { 83 size_t j; 84 for (j = 0; j < __arraycount(nv); j++) 85 if (strcmp(nv[j].n, argv[i]) == 0) { 86 flags |= nv[j].v; 87 break; 88 } 89 if (j == __arraycount(nv)) 90 usage(); 91 } 92 93 if (flags == 0) 94 usage(); 95 96 if (flags & F_HANDLE) { 97 struct sigaction sa; 98 99 sa.sa_flags = SA_RESTART; 100 sa.sa_handler = foo; 101 sigemptyset(&sa.sa_mask); 102 if (sigaction(SIGSEGV, &sa, NULL) == -1) 103 err(EXIT_FAILURE, "sigaction"); 104 } 105 106 if (flags & F_MASK) { 107 sigset_t set; 108 109 sigemptyset(&set); 110 sigaddset(&set, SIGSEGV); 111 if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) 112 err(EXIT_FAILURE, "sigprocmask"); 113 } 114 115 *p = 1; 116 return EXIT_SUCCESS; 117 } 118