From: mvs Date: Tue, 11 Jan 2022 08:03:25 +0000 (+0000) Subject: Produce alive in-flight sockets with positive "f_count == unp_msgcount" X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=87ba1692fe088bccf148acb44744bc6602d43246;p=openbsd Produce alive in-flight sockets with positive "f_count == unp_msgcount" equation. Such sockets should not be killed by unp_gc() otherwise system will panic. tested by anton@; ok bluhm@ --- diff --git a/regress/sys/kern/unixsockets/ungc.c b/regress/sys/kern/unixsockets/ungc.c index 6f08c5672f6..6cbc9e0eb0b 100644 --- a/regress/sys/kern/unixsockets/ungc.c +++ b/regress/sys/kern/unixsockets/ungc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ungc.c,v 1.2 2021/12/15 21:25:55 bluhm Exp $ */ +/* $OpenBSD: ungc.c,v 1.3 2022/01/11 08:03:25 mvs Exp $ */ /* * Copyright (c) 2021 Vitaliy Makkoveev @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) struct iovec iov; struct msghdr msgh; struct cmsghdr *cmsgh; - int s[2]; + int sp[2], sl[2], ts; int infinite = 0; if (argc > 1 && !strcmp(argv[1], "--infinite")) @@ -52,7 +52,60 @@ int main(int argc, char *argv[]) err(1, "clock_gettime"); while (1) { - if (socketpair(AF_UNIX, SOCK_STREAM|O_NONBLOCK, 0, s) < 0) + if (socketpair(AF_UNIX, SOCK_STREAM|O_NONBLOCK, 0, sp) < 0) + err(1, "socketpair"); + + iov_buf = 0; + iov.iov_base = &iov_buf; + iov.iov_len = sizeof(iov_buf); + msgh.msg_control = msg_control.control; + msgh.msg_controllen = sizeof(msg_control.control); + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + msgh.msg_name = NULL; + msgh.msg_namelen = 0; + cmsgh = CMSG_FIRSTHDR(&msgh); + cmsgh->cmsg_len = CMSG_LEN(sizeof(int)); + cmsgh->cmsg_level = SOL_SOCKET; + cmsgh->cmsg_type = SCM_RIGHTS; + + *((int *)CMSG_DATA(cmsgh)) = sp[0]; + + if (sendmsg(sp[0], &msgh, 0) < 0) { + if (errno == EMFILE) { + /* Too may sockets in flight */ + close(sp[0]); + goto skip; + } + + err(1, "sendmsg"); + } + + *((int *)CMSG_DATA(cmsgh)) = sp[1]; + + if (sendmsg(sp[1], &msgh, 0) < 0) { + if (errno == EMFILE) { + /* Too may sockets in flight */ + close(sp[0]); + goto skip; + } + + err(1, "sendmsg"); + } + + /* + * After following close(2), the sp[0] socket has + * f_count equal to unp_msgcount. This socket is not + * in the loop and should not be killed by unp_gc(). + * This sockets should be successfully received. + * The sp[1] socket is stored within sp[0] receive + * buffer. This socket should be also successfully + * received. + */ + + close(sp[0]); + + if (socketpair(AF_UNIX, SOCK_STREAM|O_NONBLOCK, 0, sl) < 0) err(1, "socketpair"); iov_buf = 0; @@ -68,16 +121,63 @@ int main(int argc, char *argv[]) cmsgh->cmsg_len = CMSG_LEN(sizeof(int) * 2); cmsgh->cmsg_level = SOL_SOCKET; cmsgh->cmsg_type = SCM_RIGHTS; - *((int *)CMSG_DATA(cmsgh) + 0) = s[0]; - *((int *)CMSG_DATA(cmsgh) + 1) = s[1]; + *((int *)CMSG_DATA(cmsgh) + 0) = sl[0]; + *((int *)CMSG_DATA(cmsgh) + 1) = sl[1]; - if (sendmsg(s[0], &msgh, 0) < 0) { + if (sendmsg(sl[0], &msgh, 0) < 0) { if (errno != EMFILE) err(1, "sendmsg"); } - close(s[0]); - close(s[1]); + /* + * After following close(2), the sl[0] socket is not + * in the loop and should be disposed by sorflush(). + * The sl[1] socket is in the loop and should be + * killed by unp_gc(). + */ + + close(sl[0]); + close(sl[1]); + + if (recvmsg(sp[1], &msgh, 0) < 0) { + if (errno == EMSGSIZE) + goto skip; + err(1, "recvmsg"); + } + + if (!(cmsgh = CMSG_FIRSTHDR(&msgh))) + errx(1, "bad cmsg header"); + if (cmsgh->cmsg_level != SOL_SOCKET) + errx(1, "bad cmsg level"); + if (cmsgh->cmsg_type != SCM_RIGHTS) + errx(1, "bad cmsg type"); + if (cmsgh->cmsg_len != CMSG_LEN(sizeof(ts))) + errx(1, "bad cmsg length"); + + ts = *((int *)CMSG_DATA(cmsgh)); + + if (recvmsg(ts, &msgh, 0) < 0) { + if (errno == EMSGSIZE) + goto skip; + err(1, "recvmsg"); + } + + close(ts); + + if (!(cmsgh = CMSG_FIRSTHDR(&msgh))) + errx(1, "bad cmsg header"); + if (cmsgh->cmsg_level != SOL_SOCKET) + errx(1, "bad cmsg level"); + if (cmsgh->cmsg_type != SCM_RIGHTS) + errx(1, "bad cmsg type"); + if (cmsgh->cmsg_len != CMSG_LEN(sizeof(ts))) + errx(1, "bad cmsg length"); + + ts = *((int *)CMSG_DATA(cmsgh)); + close(ts); + +skip: + close(sp[1]); if (!infinite) { if (clock_gettime(CLOCK_BOOTTIME, &ts_now) <0)