Path: blob/main/tests/sys/kern/sysctl_kern_proc.c
104396 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2021 The FreeBSD Foundation4*5* This software was developed by Mark Johnston under sponsorship from6* the FreeBSD Foundation.7*/89#include <sys/param.h>10#include <sys/stat.h>11#include <sys/sysctl.h>12#include <sys/user.h>13#include <sys/wait.h>1415#include <stdio.h>16#include <stdlib.h>17#include <string.h>18#include <unistd.h>1920#include <atf-c.h>2122/*23* These tests exercise the KERN_PROC_* sysctls.24*/2526/*27* Loop through all valid PIDs and try to fetch info for each one.28*/29static void30sysctl_kern_proc_all(int cmd)31{32int mib[4], pid_max;33void *buf;34size_t sz;3536sz = sizeof(pid_max);37ATF_REQUIRE(sysctlbyname("kern.pid_max", &pid_max, &sz, NULL, 0) == 0);3839mib[0] = CTL_KERN;40mib[1] = KERN_PROC;41mib[2] = cmd;42for (int i = 1; i <= pid_max; i++) {43mib[3] = i;4445if (sysctl(mib, 4, NULL, &sz, NULL, 0) == 0) {46buf = malloc(sz);47ATF_REQUIRE(buf != NULL);48(void)sysctl(mib, 4, buf, &sz, NULL, 0);49free(buf);50}51}5253mib[3] = -1;54ATF_REQUIRE_ERRNO(ESRCH, sysctl(mib, 4, NULL, &sz, NULL, 0) != 0);55}5657/*58* Validate behaviour of the KERN_PROC_CWD sysctl.59*/60ATF_TC_WITHOUT_HEAD(sysctl_kern_proc_cwd);61ATF_TC_BODY(sysctl_kern_proc_cwd, tc)62{63struct kinfo_file kfile;64char cwd[PATH_MAX];65int cmd, mib[4];66size_t sz;67pid_t child;68int status;6970cmd = KERN_PROC_CWD;7172mib[0] = CTL_KERN;73mib[1] = KERN_PROC;74mib[2] = cmd;75mib[3] = getpid();7677/* Try querying the kernel for the output buffer size. */78sz = 0;79ATF_REQUIRE(sysctl(mib, 4, NULL, &sz, NULL, 0) == 0);80ATF_REQUIRE(sz <= sizeof(kfile));8182sz = sizeof(kfile);83memset(&kfile, 0, sz);84ATF_REQUIRE(sysctl(mib, 4, &kfile, &sz, NULL, 0) == 0);85ATF_REQUIRE(sz <= sizeof(kfile));86ATF_REQUIRE(sz == (u_int)kfile.kf_structsize);8788/* Make sure that we get the same result from getcwd(2). */89ATF_REQUIRE(getcwd(cwd, sizeof(cwd)) == cwd);90ATF_REQUIRE(strcmp(cwd, kfile.kf_path) == 0);9192/* Spot-check some of the kinfo fields. */93ATF_REQUIRE(kfile.kf_type == KF_TYPE_VNODE);94ATF_REQUIRE(kfile.kf_fd == KF_FD_TYPE_CWD);95ATF_REQUIRE(S_ISDIR(kfile.kf_un.kf_file.kf_file_mode));96ATF_REQUIRE((kfile.kf_status & KF_ATTR_VALID) != 0);9798/*99* Verify that a child process can get our CWD info, and that it100* matches the info we got above.101*/102child = fork();103ATF_REQUIRE(child != -1);104if (child == 0) {105struct kinfo_file pkfile;106107mib[0] = CTL_KERN;108mib[1] = KERN_PROC;109mib[2] = KERN_PROC_CWD;110mib[3] = getppid();111112sz = sizeof(pkfile);113memset(&pkfile, 0, sz);114if (sysctl(mib, 4, &pkfile, &sz, NULL, 0) != 0)115_exit(1);116if (memcmp(&kfile, &pkfile, sizeof(kfile)) != 0)117_exit(2);118_exit(0);119}120ATF_REQUIRE(waitpid(child, &status, 0) == child);121ATF_REQUIRE(WIFEXITED(status));122ATF_REQUIRE(WEXITSTATUS(status) == 0);123124/*125* Truncate the output buffer ever so slightly and make sure that we get126* an error.127*/128sz--;129ATF_REQUIRE_ERRNO(ENOMEM, sysctl(mib, 4, &kfile, &sz, NULL, 0) != 0);130131sysctl_kern_proc_all(cmd);132}133134/*135* Validate behaviour of the KERN_PROC_FILEDESC sysctl.136*/137ATF_TC_WITHOUT_HEAD(sysctl_kern_proc_filedesc);138ATF_TC_BODY(sysctl_kern_proc_filedesc, tc)139{140int cmd, fd, mib[4];141struct kinfo_file *kfile;142char *buf, tmp[16];143size_t sz, sz1;144145cmd = KERN_PROC_FILEDESC;146147mib[0] = CTL_KERN;148mib[1] = KERN_PROC;149mib[2] = cmd;150mib[3] = getpid();151152sz = 0;153ATF_REQUIRE(sysctl(mib, 4, NULL, &sz, NULL, 0) == 0);154ATF_REQUIRE(sz >= __offsetof(struct kinfo_file, kf_structsize) +155sizeof(kfile->kf_structsize));156157buf = malloc(sz);158ATF_REQUIRE(buf != NULL);159160ATF_REQUIRE(sysctl(mib, 4, buf, &sz, NULL, 0) == 0);161162/* Walk over the list of returned files. */163for (sz1 = 0; sz1 < sz; sz1 += kfile->kf_structsize) {164kfile = (void *)(buf + sz1);165166ATF_REQUIRE((unsigned int)kfile->kf_structsize <= sz);167ATF_REQUIRE((unsigned int)kfile->kf_structsize + sz1 <= sz);168169ATF_REQUIRE((kfile->kf_status & KF_ATTR_VALID) != 0);170}171/* We shouldn't have any trailing bytes. */172ATF_REQUIRE(sz1 == sz);173174/*175* Open a file. This increases the size of the output buffer, so an176* attempt to re-fetch the records without increasing the buffer size177* should fail with ENOMEM.178*/179snprintf(tmp, sizeof(tmp), "tmp.XXXXXX");180fd = mkstemp(tmp);181ATF_REQUIRE(fd >= 0);182ATF_REQUIRE_ERRNO(ENOMEM, sysctl(mib, 4, buf, &sz, NULL, 0) != 0);183184ATF_REQUIRE(unlink(tmp) == 0);185ATF_REQUIRE(close(fd) == 0);186187free(buf);188189sysctl_kern_proc_all(cmd);190}191192ATF_TP_ADD_TCS(tp)193{194ATF_TP_ADD_TC(tp, sysctl_kern_proc_cwd);195ATF_TP_ADD_TC(tp, sysctl_kern_proc_filedesc);196197return (atf_no_error());198}199200201