1/*-
2 * Copyright (c) 2023 Dmitry Chagin <dchagin@FreeBSD.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 *
6 * PR:	272585
7 * Test provided by John F. Carr
8 */
9
10#include <sys/systm.h>
11#include <sys/mman.h>
12#include <vm/vm_param.h>
13
14#include <atf-c.h>
15#include <signal.h>
16#include <unistd.h>
17
18static void
19sigsegv_handler(int sig __unused)
20{
21
22	atf_tc_fail("Invalid stack protection mode after grows");
23}
24
25ATF_TC_WITHOUT_HEAD(mprotect_exec_test);
26ATF_TC_BODY(mprotect_exec_test, tc)
27{
28	long pagesize;
29	char *addr, *guard;
30	size_t alloc_size;
31
32	signal(SIGSEGV, sigsegv_handler);
33
34	pagesize = sysconf(_SC_PAGESIZE);
35	ATF_REQUIRE(pagesize > 0);
36
37	alloc_size = SGROWSIZ * 2;
38	addr = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE,
39	    MAP_STACK | MAP_PRIVATE | MAP_ANON, -1, 0);
40	ATF_REQUIRE(addr != MAP_FAILED);
41
42	/*
43	 * Change prot of the last page in the mmaped stack area.
44	 */
45	guard = addr + alloc_size - SGROWSIZ;
46	ATF_REQUIRE(mprotect(guard, pagesize, PROT_NONE) == 0);
47
48	((volatile char *)guard)[-1];
49}
50
51ATF_TP_ADD_TCS(tp)
52{
53
54	ATF_TP_ADD_TC(tp, mprotect_exec_test);
55
56	return (atf_no_error());
57}
58