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