2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2021 The FreeBSD Foundation
6 * This software was developed by Mark Johnston under sponsorship from
7 * the FreeBSD Foundation.
10 #include <sys/param.h>
12 #include <sys/sysctl.h>
24 * These tests exercise the KERN_PROC_* sysctls.
28 * Loop through all valid PIDs and try to fetch info for each one.
31 sysctl_kern_proc_all(int cmd)
38 ATF_REQUIRE(sysctlbyname("kern.pid_max", &pid_max, &sz, NULL, 0) == 0);
43 for (int i = 1; i <= pid_max; i++) {
46 if (sysctl(mib, 4, NULL, &sz, NULL, 0) == 0) {
48 ATF_REQUIRE(buf != NULL);
49 (void)sysctl(mib, 4, buf, &sz, NULL, 0);
55 ATF_REQUIRE_ERRNO(ESRCH, sysctl(mib, 4, NULL, &sz, NULL, 0) != 0);
59 * Validate behaviour of the KERN_PROC_CWD sysctl.
61 ATF_TC_WITHOUT_HEAD(sysctl_kern_proc_cwd);
62 ATF_TC_BODY(sysctl_kern_proc_cwd, tc)
64 struct kinfo_file kfile;
78 /* Try querying the kernel for the output buffer size. */
80 ATF_REQUIRE(sysctl(mib, 4, NULL, &sz, NULL, 0) == 0);
81 ATF_REQUIRE(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);
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);
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);
100 * Verify that a child process can get our CWD info, and that it
101 * matches the info we got above.
104 ATF_REQUIRE(child != -1);
106 struct kinfo_file pkfile;
110 mib[2] = KERN_PROC_CWD;
114 memset(&pkfile, 0, sz);
115 if (sysctl(mib, 4, &pkfile, &sz, NULL, 0) != 0)
117 if (memcmp(&kfile, &pkfile, sizeof(kfile)) != 0)
121 ATF_REQUIRE(waitpid(child, &status, 0) == child);
122 ATF_REQUIRE(WIFEXITED(status));
123 ATF_REQUIRE(WEXITSTATUS(status) == 0);
126 * Truncate the output buffer ever so slightly and make sure that we get
130 ATF_REQUIRE_ERRNO(ENOMEM, sysctl(mib, 4, &kfile, &sz, NULL, 0) != 0);
132 sysctl_kern_proc_all(cmd);
136 * Validate behaviour of the KERN_PROC_FILEDESC sysctl.
138 ATF_TC_WITHOUT_HEAD(sysctl_kern_proc_filedesc);
139 ATF_TC_BODY(sysctl_kern_proc_filedesc, tc)
142 struct kinfo_file *kfile;
146 cmd = KERN_PROC_FILEDESC;
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));
159 ATF_REQUIRE(buf != NULL);
161 ATF_REQUIRE(sysctl(mib, 4, buf, &sz, NULL, 0) == 0);
163 /* Walk over the list of returned files. */
164 for (sz1 = 0; sz1 < sz; sz1 += kfile->kf_structsize) {
165 kfile = (void *)(buf + sz1);
167 ATF_REQUIRE((unsigned int)kfile->kf_structsize <= sz);
168 ATF_REQUIRE((unsigned int)kfile->kf_structsize + sz1 <= sz);
170 ATF_REQUIRE((kfile->kf_status & KF_ATTR_VALID) != 0);
172 /* We shouldn't have any trailing bytes. */
173 ATF_REQUIRE(sz1 == sz);
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.
180 snprintf(tmp, sizeof(tmp), "tmp.XXXXXX");
182 ATF_REQUIRE(fd >= 0);
183 ATF_REQUIRE_ERRNO(ENOMEM, sysctl(mib, 4, buf, &sz, NULL, 0) != 0);
185 ATF_REQUIRE(unlink(tmp) == 0);
186 ATF_REQUIRE(close(fd) == 0);
190 sysctl_kern_proc_all(cmd);
195 ATF_TP_ADD_TC(tp, sysctl_kern_proc_cwd);
196 ATF_TP_ADD_TC(tp, sysctl_kern_proc_filedesc);
198 return (atf_no_error());