/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2024 Gleb Smirnoff <[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 AUTHOR 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 AUTHOR 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/socket.h>28#include <sys/un.h>29#include <assert.h>30#include <errno.h>31#include <pthread.h>32#include <unistd.h>33#include <netinet/in.h>3435#include <atf-c.h>3637/*38* shutdown(2) on SOCK_DGRAM shall return ENOTCONN per POSIX. However, there39* is historical behavior of the shutdown(2) also unblocking any ongoing40* recv(2) syscall on the socket. It is known that some programs rely on this41* behavior, but exact list of programs isn't known. Neither we know if the42* "feature" is required on PF_UNIX sockets or on PF_INET/INET6 sockets or43* on both kinds. Feel free to improve this comment if you know any details.44*45* List of relevant commits, bug reports and reviews:46* 63649db0420547* https://reviews.freebsd.org/D1035148* b114aa79596c (regresses)49* https://reviews.freebsd.org/D3039 (regresses)50* kern/84761 c5cff17017f9 aada5cccd87851*/525354static void *55blocking_thread(void *arg)56{57int *s = arg;58char buf[1];59int error, rv;6061rv = recv(*s, buf, sizeof(buf), 0);62error = (rv == -1) ? errno : 0;6364return ((void *)(uintptr_t)error);65}6667static void68shutdown_thread(int s)69{70pthread_t t;71int rv;7273ATF_REQUIRE(pthread_create(&t, NULL, blocking_thread, &s) == 0);74usleep(1000);75ATF_REQUIRE(shutdown(s, SHUT_RD) == -1);76ATF_REQUIRE(errno == ENOTCONN);77ATF_REQUIRE(pthread_join(t, (void *)&rv) == 0);78ATF_REQUIRE(rv == 0);79close(s);80}8182ATF_TC_WITHOUT_HEAD(unblock);83ATF_TC_BODY(unblock, tc)84{85static const struct sockaddr_un sun = {86.sun_family = AF_LOCAL,87.sun_len = sizeof(sun),88.sun_path = "shutdown-dgram-test-sock",89};90int s;9192ATF_REQUIRE((s = socket(PF_UNIX, SOCK_DGRAM, 0)) >= 0);93ATF_REQUIRE(bind(s, (struct sockaddr *)&sun, sizeof(sun)) == 0);94shutdown_thread(s);9596static const struct sockaddr_in sin = {97.sin_family = AF_INET,98.sin_len = sizeof(sin),99};100ATF_REQUIRE((s = socket(PF_INET, SOCK_DGRAM, 0)) >= 0);101ATF_REQUIRE(bind(s, (struct sockaddr *)&sin, sizeof(sin)) == 0);102shutdown_thread(s);103}104105ATF_TP_ADD_TCS(tp)106{107ATF_TP_ADD_TC(tp, unblock);108109return (atf_no_error());110}111112113