Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/kern/sysctl_kern_proc.c
39536 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2021 The FreeBSD Foundation
5
*
6
* This software was developed by Mark Johnston under sponsorship from
7
* the FreeBSD Foundation.
8
*/
9
10
#include <sys/param.h>
11
#include <sys/stat.h>
12
#include <sys/sysctl.h>
13
#include <sys/user.h>
14
#include <sys/wait.h>
15
16
#include <stdio.h>
17
#include <stdlib.h>
18
#include <string.h>
19
#include <unistd.h>
20
21
#include <atf-c.h>
22
23
/*
24
* These tests exercise the KERN_PROC_* sysctls.
25
*/
26
27
/*
28
* Loop through all valid PIDs and try to fetch info for each one.
29
*/
30
static void
31
sysctl_kern_proc_all(int cmd)
32
{
33
int mib[4], pid_max;
34
void *buf;
35
size_t sz;
36
37
sz = sizeof(pid_max);
38
ATF_REQUIRE(sysctlbyname("kern.pid_max", &pid_max, &sz, NULL, 0) == 0);
39
40
mib[0] = CTL_KERN;
41
mib[1] = KERN_PROC;
42
mib[2] = cmd;
43
for (int i = 1; i <= pid_max; i++) {
44
mib[3] = i;
45
46
if (sysctl(mib, 4, NULL, &sz, NULL, 0) == 0) {
47
buf = malloc(sz);
48
ATF_REQUIRE(buf != NULL);
49
(void)sysctl(mib, 4, buf, &sz, NULL, 0);
50
free(buf);
51
}
52
}
53
54
mib[3] = -1;
55
ATF_REQUIRE_ERRNO(ESRCH, sysctl(mib, 4, NULL, &sz, NULL, 0) != 0);
56
}
57
58
/*
59
* Validate behaviour of the KERN_PROC_CWD sysctl.
60
*/
61
ATF_TC_WITHOUT_HEAD(sysctl_kern_proc_cwd);
62
ATF_TC_BODY(sysctl_kern_proc_cwd, tc)
63
{
64
struct kinfo_file kfile;
65
char cwd[PATH_MAX];
66
int cmd, mib[4];
67
size_t sz;
68
pid_t child;
69
int status;
70
71
cmd = KERN_PROC_CWD;
72
73
mib[0] = CTL_KERN;
74
mib[1] = KERN_PROC;
75
mib[2] = cmd;
76
mib[3] = getpid();
77
78
/* Try querying the kernel for the output buffer size. */
79
sz = 0;
80
ATF_REQUIRE(sysctl(mib, 4, NULL, &sz, NULL, 0) == 0);
81
ATF_REQUIRE(sz <= sizeof(kfile));
82
83
sz = sizeof(kfile);
84
memset(&kfile, 0, sz);
85
ATF_REQUIRE(sysctl(mib, 4, &kfile, &sz, NULL, 0) == 0);
86
ATF_REQUIRE(sz <= sizeof(kfile));
87
ATF_REQUIRE(sz == (u_int)kfile.kf_structsize);
88
89
/* Make sure that we get the same result from getcwd(2). */
90
ATF_REQUIRE(getcwd(cwd, sizeof(cwd)) == cwd);
91
ATF_REQUIRE(strcmp(cwd, kfile.kf_path) == 0);
92
93
/* Spot-check some of the kinfo fields. */
94
ATF_REQUIRE(kfile.kf_type == KF_TYPE_VNODE);
95
ATF_REQUIRE(kfile.kf_fd == KF_FD_TYPE_CWD);
96
ATF_REQUIRE(S_ISDIR(kfile.kf_un.kf_file.kf_file_mode));
97
ATF_REQUIRE((kfile.kf_status & KF_ATTR_VALID) != 0);
98
99
/*
100
* Verify that a child process can get our CWD info, and that it
101
* matches the info we got above.
102
*/
103
child = fork();
104
ATF_REQUIRE(child != -1);
105
if (child == 0) {
106
struct kinfo_file pkfile;
107
108
mib[0] = CTL_KERN;
109
mib[1] = KERN_PROC;
110
mib[2] = KERN_PROC_CWD;
111
mib[3] = getppid();
112
113
sz = sizeof(pkfile);
114
memset(&pkfile, 0, sz);
115
if (sysctl(mib, 4, &pkfile, &sz, NULL, 0) != 0)
116
_exit(1);
117
if (memcmp(&kfile, &pkfile, sizeof(kfile)) != 0)
118
_exit(2);
119
_exit(0);
120
}
121
ATF_REQUIRE(waitpid(child, &status, 0) == child);
122
ATF_REQUIRE(WIFEXITED(status));
123
ATF_REQUIRE(WEXITSTATUS(status) == 0);
124
125
/*
126
* Truncate the output buffer ever so slightly and make sure that we get
127
* an error.
128
*/
129
sz--;
130
ATF_REQUIRE_ERRNO(ENOMEM, sysctl(mib, 4, &kfile, &sz, NULL, 0) != 0);
131
132
sysctl_kern_proc_all(cmd);
133
}
134
135
/*
136
* Validate behaviour of the KERN_PROC_FILEDESC sysctl.
137
*/
138
ATF_TC_WITHOUT_HEAD(sysctl_kern_proc_filedesc);
139
ATF_TC_BODY(sysctl_kern_proc_filedesc, tc)
140
{
141
int cmd, fd, mib[4];
142
struct kinfo_file *kfile;
143
char *buf, tmp[16];
144
size_t sz, sz1;
145
146
cmd = KERN_PROC_FILEDESC;
147
148
mib[0] = CTL_KERN;
149
mib[1] = KERN_PROC;
150
mib[2] = cmd;
151
mib[3] = getpid();
152
153
sz = 0;
154
ATF_REQUIRE(sysctl(mib, 4, NULL, &sz, NULL, 0) == 0);
155
ATF_REQUIRE(sz >= __offsetof(struct kinfo_file, kf_structsize) +
156
sizeof(kfile->kf_structsize));
157
158
buf = malloc(sz);
159
ATF_REQUIRE(buf != NULL);
160
161
ATF_REQUIRE(sysctl(mib, 4, buf, &sz, NULL, 0) == 0);
162
163
/* Walk over the list of returned files. */
164
for (sz1 = 0; sz1 < sz; sz1 += kfile->kf_structsize) {
165
kfile = (void *)(buf + sz1);
166
167
ATF_REQUIRE((unsigned int)kfile->kf_structsize <= sz);
168
ATF_REQUIRE((unsigned int)kfile->kf_structsize + sz1 <= sz);
169
170
ATF_REQUIRE((kfile->kf_status & KF_ATTR_VALID) != 0);
171
}
172
/* We shouldn't have any trailing bytes. */
173
ATF_REQUIRE(sz1 == sz);
174
175
/*
176
* Open a file. This increases the size of the output buffer, so an
177
* attempt to re-fetch the records without increasing the buffer size
178
* should fail with ENOMEM.
179
*/
180
snprintf(tmp, sizeof(tmp), "tmp.XXXXXX");
181
fd = mkstemp(tmp);
182
ATF_REQUIRE(fd >= 0);
183
ATF_REQUIRE_ERRNO(ENOMEM, sysctl(mib, 4, buf, &sz, NULL, 0) != 0);
184
185
ATF_REQUIRE(unlink(tmp) == 0);
186
ATF_REQUIRE(close(fd) == 0);
187
188
free(buf);
189
190
sysctl_kern_proc_all(cmd);
191
}
192
193
ATF_TP_ADD_TCS(tp)
194
{
195
ATF_TP_ADD_TC(tp, sysctl_kern_proc_cwd);
196
ATF_TP_ADD_TC(tp, sysctl_kern_proc_filedesc);
197
198
return (atf_no_error());
199
}
200
201