Path: blob/main/lib/libcasper/tests/cap_main_test.c
288947 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2026 Mariusz Zaborski <[email protected]>4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/2627#include <sys/resource.h>28#include <sys/select.h>2930#include <errno.h>31#include <inttypes.h>32#include <stdlib.h>33#include <string.h>3435#include <libcasper.h>3637#include <atf-c.h>3839#define NCONNECTIONS (FD_SETSIZE + 64)40#define FD_HEADROOM 644142/* Test that file descriptors past FD_SETSIZE (1024) work. */43ATF_TC_WITHOUT_HEAD(many_connections);44ATF_TC_BODY(many_connections, tc)45{46struct rlimit rl;47cap_channel_t *chan;48cap_channel_t **clones;49size_t i;5051if (getrlimit(RLIMIT_NOFILE, &rl) != 0)52atf_tc_skip("getrlimit: %s", strerror(errno));53if (rl.rlim_max < NCONNECTIONS + FD_HEADROOM)54atf_tc_skip("RLIMIT_NOFILE hard cap %ju below required %d",55(uintmax_t)rl.rlim_max, NCONNECTIONS + FD_HEADROOM);56rl.rlim_cur = rl.rlim_max;57ATF_REQUIRE_MSG(setrlimit(RLIMIT_NOFILE, &rl) == 0,58"setrlimit: %s", strerror(errno));5960chan = cap_init();61ATF_REQUIRE_MSG(chan != NULL, "cap_init failed: %s", strerror(errno));6263clones = calloc(NCONNECTIONS, sizeof(*clones));64ATF_REQUIRE(clones != NULL);6566/*67* Every cap_clone(3) adds one more connection to the helper.68* After this loop the helper is watching more fds than an69* fd_set can hold.70*/71for (i = 0; i < NCONNECTIONS; i++) {72clones[i] = cap_clone(chan);73ATF_REQUIRE_MSG(clones[i] != NULL,74"cap_clone failed at %zu/%d: %s",75i, NCONNECTIONS, strerror(errno));76}7778for (i = 0; i < NCONNECTIONS; i++)79cap_close(clones[i]);80free(clones);81cap_close(chan);82}8384#define CHURN_CONNECTIONS 5085#define CHURN_CLOSE_STEP 58687/* Test that gaps in the file descriptor list do not break casper. */88ATF_TC_WITHOUT_HEAD(connection_churn);89ATF_TC_BODY(connection_churn, tc)90{91cap_channel_t *chan, *survivor, *extra;92cap_channel_t *clones[CHURN_CONNECTIONS];93size_t i, survivor_idx;9495chan = cap_init();96ATF_REQUIRE_MSG(chan != NULL, "cap_init failed: %s", strerror(errno));9798for (i = 0; i < CHURN_CONNECTIONS; i++) {99clones[i] = cap_clone(chan);100ATF_REQUIRE_MSG(clones[i] != NULL,101"cap_clone failed at %zu: %s", i, strerror(errno));102}103104/*105* Close every Nth clone.106*/107for (i = 0; i < CHURN_CONNECTIONS; i += CHURN_CLOSE_STEP) {108cap_close(clones[i]);109clones[i] = NULL;110}111112/*113* Force a poll() cycle: the helper handles POLLIN on chan and114* POLLHUP on the closed clones in the same walk.115*/116extra = cap_clone(chan);117ATF_REQUIRE_MSG(extra != NULL, "cap_clone after churn failed: %s",118strerror(errno));119120/* A surviving clone must still round-trip. */121survivor_idx = 1;122survivor = cap_clone(clones[survivor_idx]);123ATF_REQUIRE_MSG(survivor != NULL,124"cap_clone on survivor failed: %s", strerror(errno));125126cap_close(survivor);127cap_close(extra);128for (i = 0; i < CHURN_CONNECTIONS; i++) {129if (clones[i] != NULL)130cap_close(clones[i]);131}132cap_close(chan);133}134135ATF_TP_ADD_TCS(tp)136{137138ATF_TP_ADD_TC(tp, many_connections);139ATF_TP_ADD_TC(tp, connection_churn);140return (atf_no_error());141}142143144