File: sigaltstack.c

package info (click to toggle)
criu 4.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 11,584 kB
  • sloc: ansic: 139,280; python: 7,484; sh: 3,824; java: 2,799; makefile: 2,659; asm: 1,137; perl: 206; xml: 117; exp: 45
file content (168 lines) | stat: -rw-r--r-- 3,652 bytes parent folder | download | duplicates (3)
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <syscall.h>

#include <sys/types.h>
#include <sys/wait.h>

#include "zdtmtst.h"

const char *test_doc = "Check for alternate signal stack";
const char *test_author = "Cyrill Gorcunov <gorcunov@openvz.org>";

#define TESTSIGSTKSZ 16384

static char stack_thread[TESTSIGSTKSZ + TEST_MSG_BUFFER_SIZE] __stack_aligned__;
static char stack_main[TESTSIGSTKSZ + TEST_MSG_BUFFER_SIZE] __stack_aligned__;

enum {
	SAS_MAIN_OLD,
	SAS_MAIN_NEW,
	SAS_THRD_OLD,
	SAS_THRD_NEW,

	SAS_MAX
};
static stack_t sas_state[SAS_MAX];

static task_waiter_t t;

#define exit_group(code) syscall(__NR_exit_group, code)
#define gettid()	 syscall(__NR_gettid)

static int sascmp(stack_t *old, stack_t *new)
{
	return old->ss_size != new->ss_size || old->ss_sp != new->ss_sp || old->ss_flags != new->ss_flags;
}

static void show_ss(char *prefix, stack_t *s)
{
	test_msg("%20s: at %p (size %8zu flags %#2x)\n", prefix, s->ss_sp, s->ss_size, s->ss_flags);
}

void thread_sigaction(int signo, siginfo_t *info, void *context)
{
	if (sigaltstack(NULL, &sas_state[SAS_THRD_NEW]))
		pr_perror("thread sigaltstack");

	show_ss("thread in sas", &sas_state[SAS_THRD_NEW]);

	task_waiter_complete(&t, 2);

	test_msg("Waiting in thread SAS\n");
	task_waiter_wait4(&t, 3);
	test_msg("Leaving thread SAS\n");
}

static void *thread_func(void *arg)
{
	struct sigaction sa = {
		.sa_sigaction = thread_sigaction,
		.sa_flags = SA_RESTART | SA_ONSTACK,
	};

	sas_state[SAS_THRD_OLD] = (stack_t){
		.ss_size = sizeof(stack_thread) - 8,
		.ss_sp = stack_thread,
		.ss_flags = 0,
	};

	sigemptyset(&sa.sa_mask);

	if (sigaction(SIGUSR2, &sa, NULL)) {
		pr_perror("Can't set SIGUSR2 handler");
		exit_group(-1);
	}

	task_waiter_wait4(&t, 1);

	if (sigaltstack(&sas_state[SAS_THRD_OLD], NULL)) {
		pr_perror("thread sigaltstack");
		exit_group(-1);
	}

	syscall(__NR_tkill, gettid(), SIGUSR2);

	return NULL;
}

void leader_sigaction(int signo, siginfo_t *info, void *context)
{
	if (sigaltstack(NULL, &sas_state[SAS_MAIN_NEW]))
		pr_perror("leader sigaltstack");

	show_ss("leader in sas", &sas_state[SAS_MAIN_NEW]);
}

int main(int argc, char *argv[])
{
	pthread_t thread;

	struct sigaction sa = {
		.sa_sigaction = leader_sigaction,
		.sa_flags = SA_RESTART | SA_ONSTACK,
	};

	sas_state[SAS_MAIN_OLD] = (stack_t){
		.ss_size = sizeof(stack_main) - 8,
		.ss_sp = stack_main,
		.ss_flags = 0,
	};

	sigemptyset(&sa.sa_mask);

	test_init(argc, argv);
	task_waiter_init(&t);

	if (sigaction(SIGUSR1, &sa, NULL)) {
		pr_perror("Can't set SIGUSR1 handler");
		exit(-1);
	}

	if (pthread_create(&thread, NULL, &thread_func, NULL)) {
		pr_perror("Can't create thread");
		exit(-1);
	}

	if (sigaltstack(&sas_state[SAS_MAIN_OLD], NULL)) {
		pr_perror("sigaltstack");
		exit(-1);
	}

	task_waiter_complete(&t, 1);
	task_waiter_wait4(&t, 2);

	test_daemon();
	test_waitsig();

	test_msg("Thread may leave SAS\n");
	task_waiter_complete(&t, 3);

	syscall(__NR_tkill, gettid(), SIGUSR1);

	if (pthread_join(thread, NULL)) {
		fail("Error joining thread");
		exit(-1);
	}
	task_waiter_fini(&t);

	sas_state[SAS_THRD_OLD].ss_flags = SS_ONSTACK;
	sas_state[SAS_MAIN_OLD].ss_flags = SS_ONSTACK;

	show_ss("main old", &sas_state[SAS_MAIN_OLD]);
	show_ss("main new", &sas_state[SAS_MAIN_NEW]);
	show_ss("thrd old", &sas_state[SAS_THRD_OLD]);
	show_ss("thrd new", &sas_state[SAS_THRD_NEW]);

	if (sascmp(&sas_state[SAS_MAIN_OLD], &sas_state[SAS_MAIN_NEW]) ||
	    sascmp(&sas_state[SAS_THRD_OLD], &sas_state[SAS_THRD_NEW])) {
		fail("sas not restored");
	} else
		pass();

	return 0;
}