1/*-
2 * Copyright (c) 2023 Dmitry Chagin <dchagin@FreeBSD.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <sys/param.h>
8#include <sys/sysctl.h>
9#include <sys/user.h>
10
11#include <assert.h>
12#include <libprocstat.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <unistd.h>
16
17int	checkstack(void);
18
19#define	_STACK_FLAG_GROWS	(KVME_FLAG_GROWS_UP | KVME_FLAG_GROWS_DOWN)
20int
21checkstack(void)
22{
23	struct kinfo_vmentry *freep, *kve;
24	struct kinfo_proc *p;
25	struct procstat *prstat;
26	uintptr_t stack;
27	int i, cnt;
28
29	prstat = procstat_open_sysctl();
30	assert(prstat != NULL);
31	p = procstat_getprocs(prstat, KERN_PROC_PID, getpid(), &cnt);
32	assert(p != NULL);
33	freep = procstat_getvmmap(prstat, p, &cnt);
34	assert(freep != NULL);
35
36	stack = (uintptr_t)&i;
37	for (i = 0; i < cnt; i++) {
38		kve = &freep[i];
39		if (stack < kve->kve_start || stack > kve->kve_end)
40			continue;
41		if ((kve->kve_flags & _STACK_FLAG_GROWS) != 0 &&
42		    (kve->kve_protection & KVME_PROT_EXEC) != 0)
43			stack = 0;
44		break;
45	}
46
47	free(freep);
48	procstat_freeprocs(prstat, p);
49	procstat_close(prstat);
50	return (stack != 0);
51}
52