aboutsummaryrefslogtreecommitdiff
path: root/signal_handler.c
blob: 175c9ebf026b36c4cec877145b13877e3f74731c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "signal_handler.h"

#include "util.h"

/*
 * si_syscall was added in glibc-2.17+, but Android still uses glibc-2.15
 * for its prebuilt binary host toolchains.  Add a compat hack for it.
 */
static int get_si_syscall(const siginfo_t *info)
{
#if defined(si_syscall)
	return info->si_syscall;
#endif

	typedef struct {
		void		*ip;
		int		nr;
		unsigned int	arch;
	} local_siginfo_t;

	union {
		const siginfo_t *info;
		const local_siginfo_t *local_info;
	} local_info = {
		.info = info,
	};
	return local_info.local_info->nr;
}

void log_sigsys_handler(int sig attribute_unused, siginfo_t *info,
			void *void_context attribute_unused)
{
	const char *syscall_name;
	int nr = get_si_syscall(info);
	syscall_name = lookup_syscall_name(nr);

	if (syscall_name)
		die("blocked syscall: %s", syscall_name);
	else
		die("blocked syscall: %d", nr);

	/*
	 * We trapped on a syscall that should have killed the process.
	 * This should never ever return, but we're paranoid.
	 */
	for (;;)
		_exit(1);
}

int install_sigsys_handler()
{
	int ret = 0;
	struct sigaction act;
	sigset_t mask;

	memset(&act, 0, sizeof(act));
	act.sa_sigaction = &log_sigsys_handler;
	act.sa_flags = SA_SIGINFO;

	sigemptyset(&mask);
	sigaddset(&mask, SIGSYS);

	ret = sigaction(SIGSYS, &act, NULL);
	if (ret < 0)
		return ret;

	ret = sigprocmask(SIG_UNBLOCK, &mask, NULL);
	if (ret < 0)
		return ret;

	return 0;
}