h_segv.c revision 1.3
1/* $NetBSD: h_segv.c,v 1.3 2018/05/21 08:49:03 kamil 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.3 2018/05/21 08:49:03 kamil 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 42static int *p = (int *) 0xfefefef0; 43 44static int flags; 45#define F_RECURSE 1 46#define F_HANDLE 2 47#define F_MASK 4 48#define F_IGNORE 8 49 50static struct { 51 const char *n; 52 int v; 53} nv[] = { 54 { "recurse", F_RECURSE }, 55 { "handle", F_HANDLE }, 56 { "mask", F_MASK }, 57 { "ignore", F_IGNORE } 58}; 59 60static void 61foo(int s) 62{ 63 char buf[64]; 64 int i = snprintf(buf, sizeof(buf), "got %d\n", s); 65 write(2, buf, i); 66 if (flags & F_RECURSE) 67 *p = 0; 68 exit(EXIT_SUCCESS); 69} 70 71static __dead void 72usage(void) 73{ 74 fprintf(stderr, "Usage: %s recurse|mask|handle ...\n", getprogname()); 75 exit(EXIT_FAILURE); 76} 77 78int 79main(int argc, char *argv[]) 80{ 81 if (argc == 1) 82 usage(); 83 84 for (int i = 1; i < argc; i++) { 85 size_t j; 86 for (j = 0; j < __arraycount(nv); j++) 87 if (strcmp(nv[j].n, argv[i]) == 0) { 88 flags |= nv[j].v; 89 break; 90 } 91 if (j == __arraycount(nv)) 92 usage(); 93 } 94 95 if (flags == 0) 96 usage(); 97 98 if (flags & F_HANDLE) { 99 struct sigaction sa; 100 101 sa.sa_flags = SA_RESTART; 102 sa.sa_handler = foo; 103 sigemptyset(&sa.sa_mask); 104 if (sigaction(SIGSEGV, &sa, NULL) == -1) 105 err(EXIT_FAILURE, "sigaction"); 106 } 107 108 if (flags & F_MASK) { 109 sigset_t set; 110 111 sigemptyset(&set); 112 sigaddset(&set, SIGSEGV); 113 if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) 114 err(EXIT_FAILURE, "sigprocmask"); 115 } 116 117 if (flags & F_IGNORE) { 118 struct sigaction sa; 119 120 memset(&sa, 0, sizeof(sa)); 121 sa.sa_handler = SIG_IGN; 122 sigemptyset(&sa.sa_mask); 123 if (sigaction(SIGSEGV, &sa, NULL) == -1) 124 err(EXIT_FAILURE, "sigaction"); 125 } 126 127 *p = 1; 128 return EXIT_SUCCESS; 129} 130