1*0250c53aSRobert Mustacchi /*
2*0250c53aSRobert Mustacchi * This file and its contents are supplied under the terms of the
3*0250c53aSRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4*0250c53aSRobert Mustacchi * You may only use this file in accordance with the terms of version
5*0250c53aSRobert Mustacchi * 1.0 of the CDDL.
6*0250c53aSRobert Mustacchi *
7*0250c53aSRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8*0250c53aSRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9*0250c53aSRobert Mustacchi * http://www.illumos.org/license/CDDL.
10*0250c53aSRobert Mustacchi */
11*0250c53aSRobert Mustacchi
12*0250c53aSRobert Mustacchi /*
13*0250c53aSRobert Mustacchi * Copyright 2024 Oxide Computer Company
14*0250c53aSRobert Mustacchi */
15*0250c53aSRobert Mustacchi
16*0250c53aSRobert Mustacchi /*
17*0250c53aSRobert Mustacchi * Verify that unsupported flags will properly generate errors across the
18*0250c53aSRobert Mustacchi * functions that we know perform strict error checking. This includes:
19*0250c53aSRobert Mustacchi *
20*0250c53aSRobert Mustacchi * o fcntl(..., F_DUP3FD, ...)
21*0250c53aSRobert Mustacchi * o dup3()
22*0250c53aSRobert Mustacchi * o pipe2()
23*0250c53aSRobert Mustacchi * o socket()
24*0250c53aSRobert Mustacchi * o accept4()
25*0250c53aSRobert Mustacchi */
26*0250c53aSRobert Mustacchi
27*0250c53aSRobert Mustacchi #include <stdlib.h>
28*0250c53aSRobert Mustacchi #include <err.h>
29*0250c53aSRobert Mustacchi #include <stdio.h>
30*0250c53aSRobert Mustacchi #include <unistd.h>
31*0250c53aSRobert Mustacchi #include <sys/stdbool.h>
32*0250c53aSRobert Mustacchi #include <errno.h>
33*0250c53aSRobert Mustacchi #include <string.h>
34*0250c53aSRobert Mustacchi #include <fcntl.h>
35*0250c53aSRobert Mustacchi #include <limits.h>
36*0250c53aSRobert Mustacchi #include <sys/socket.h>
37*0250c53aSRobert Mustacchi
38*0250c53aSRobert Mustacchi static bool
oclo_check(const char * desc,const char * act,int ret,int e)39*0250c53aSRobert Mustacchi oclo_check(const char *desc, const char *act, int ret, int e)
40*0250c53aSRobert Mustacchi {
41*0250c53aSRobert Mustacchi if (ret >= 0) {
42*0250c53aSRobert Mustacchi warnx("TEST FAILED: %s: fd was %s!", desc, act);
43*0250c53aSRobert Mustacchi return (false);
44*0250c53aSRobert Mustacchi } else if (errno != EINVAL) {
45*0250c53aSRobert Mustacchi int e = errno;
46*0250c53aSRobert Mustacchi warnx("TEST FAILED: %s: failed with %s, expected "
47*0250c53aSRobert Mustacchi "EINVAL", desc, strerrorname_np(e));
48*0250c53aSRobert Mustacchi return (false);
49*0250c53aSRobert Mustacchi }
50*0250c53aSRobert Mustacchi
51*0250c53aSRobert Mustacchi (void) printf("TEST PASSED: %s: correctly failed with EINVAL\n",
52*0250c53aSRobert Mustacchi desc);
53*0250c53aSRobert Mustacchi return (true);
54*0250c53aSRobert Mustacchi }
55*0250c53aSRobert Mustacchi
56*0250c53aSRobert Mustacchi static bool
oclo_dup3(const char * desc,int flags)57*0250c53aSRobert Mustacchi oclo_dup3(const char *desc, int flags)
58*0250c53aSRobert Mustacchi {
59*0250c53aSRobert Mustacchi int fd = dup3(STDERR_FILENO, 23, flags);
60*0250c53aSRobert Mustacchi return (oclo_check(desc, "duplicated", fd, errno));
61*0250c53aSRobert Mustacchi }
62*0250c53aSRobert Mustacchi
63*0250c53aSRobert Mustacchi static bool
oclo_dup3fd(const char * desc,int flags)64*0250c53aSRobert Mustacchi oclo_dup3fd(const char *desc, int flags)
65*0250c53aSRobert Mustacchi {
66*0250c53aSRobert Mustacchi int fd = fcntl(STDERR_FILENO, F_DUP3FD, 23, flags);
67*0250c53aSRobert Mustacchi return (oclo_check(desc, "duplicated", fd, errno));
68*0250c53aSRobert Mustacchi }
69*0250c53aSRobert Mustacchi
70*0250c53aSRobert Mustacchi
71*0250c53aSRobert Mustacchi static bool
oclo_pipe2(const char * desc,int flags)72*0250c53aSRobert Mustacchi oclo_pipe2(const char *desc, int flags)
73*0250c53aSRobert Mustacchi {
74*0250c53aSRobert Mustacchi int fds[2], ret;
75*0250c53aSRobert Mustacchi
76*0250c53aSRobert Mustacchi ret = pipe2(fds, flags);
77*0250c53aSRobert Mustacchi return (oclo_check(desc, "piped", ret, errno));
78*0250c53aSRobert Mustacchi }
79*0250c53aSRobert Mustacchi
80*0250c53aSRobert Mustacchi static bool
oclo_socket(const char * desc,int type)81*0250c53aSRobert Mustacchi oclo_socket(const char *desc, int type)
82*0250c53aSRobert Mustacchi {
83*0250c53aSRobert Mustacchi int fd = socket(PF_UNIX, SOCK_STREAM | type, 0);
84*0250c53aSRobert Mustacchi return (oclo_check(desc, "created", fd, errno));
85*0250c53aSRobert Mustacchi }
86*0250c53aSRobert Mustacchi
87*0250c53aSRobert Mustacchi static bool
oclo_accept(const char * desc,int flags)88*0250c53aSRobert Mustacchi oclo_accept(const char *desc, int flags)
89*0250c53aSRobert Mustacchi {
90*0250c53aSRobert Mustacchi int sock, fd, e;
91*0250c53aSRobert Mustacchi struct sockaddr_in in;
92*0250c53aSRobert Mustacchi
93*0250c53aSRobert Mustacchi sock = socket(PF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
94*0250c53aSRobert Mustacchi if (sock < 0) {
95*0250c53aSRobert Mustacchi warn("TEST FAILED: %s: failed to create listen socket", desc);
96*0250c53aSRobert Mustacchi return (false);
97*0250c53aSRobert Mustacchi }
98*0250c53aSRobert Mustacchi
99*0250c53aSRobert Mustacchi (void) memset(&in, 0, sizeof (in));
100*0250c53aSRobert Mustacchi in.sin_family = AF_INET;
101*0250c53aSRobert Mustacchi in.sin_port = 0;
102*0250c53aSRobert Mustacchi in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
103*0250c53aSRobert Mustacchi
104*0250c53aSRobert Mustacchi if (bind(sock, (struct sockaddr *)&in, sizeof (in)) != 0) {
105*0250c53aSRobert Mustacchi warn("TEST FAILED: %s: failed to bind socket", desc);
106*0250c53aSRobert Mustacchi (void) close(sock);
107*0250c53aSRobert Mustacchi return (false);
108*0250c53aSRobert Mustacchi }
109*0250c53aSRobert Mustacchi
110*0250c53aSRobert Mustacchi if (listen(sock, 5) < 0) {
111*0250c53aSRobert Mustacchi warn("TEST FAILED: %s: failed to listen on socket", desc);
112*0250c53aSRobert Mustacchi (void) close(sock);
113*0250c53aSRobert Mustacchi return (false);
114*0250c53aSRobert Mustacchi }
115*0250c53aSRobert Mustacchi
116*0250c53aSRobert Mustacchi
117*0250c53aSRobert Mustacchi fd = accept4(sock, NULL, NULL, flags);
118*0250c53aSRobert Mustacchi e = errno;
119*0250c53aSRobert Mustacchi (void) close(sock);
120*0250c53aSRobert Mustacchi return (oclo_check(desc, "accepted", fd, e));
121*0250c53aSRobert Mustacchi }
122*0250c53aSRobert Mustacchi
123*0250c53aSRobert Mustacchi int
main(void)124*0250c53aSRobert Mustacchi main(void)
125*0250c53aSRobert Mustacchi {
126*0250c53aSRobert Mustacchi int ret = EXIT_SUCCESS;
127*0250c53aSRobert Mustacchi
128*0250c53aSRobert Mustacchi closefrom(STDERR_FILENO + 1);
129*0250c53aSRobert Mustacchi
130*0250c53aSRobert Mustacchi if (!oclo_dup3("dup3(): O_RDWR", O_RDWR)) {
131*0250c53aSRobert Mustacchi ret = EXIT_FAILURE;
132*0250c53aSRobert Mustacchi }
133*0250c53aSRobert Mustacchi
134*0250c53aSRobert Mustacchi if (!oclo_dup3("dup3(): O_NONBLOCK|O_CLOXEC", O_NONBLOCK | O_CLOEXEC)) {
135*0250c53aSRobert Mustacchi ret = EXIT_FAILURE;
136*0250c53aSRobert Mustacchi }
137*0250c53aSRobert Mustacchi
138*0250c53aSRobert Mustacchi if (!oclo_dup3("dup3(): O_CLOFORK|O_WRONLY", O_CLOFORK | O_WRONLY)) {
139*0250c53aSRobert Mustacchi ret = EXIT_FAILURE;
140*0250c53aSRobert Mustacchi }
141*0250c53aSRobert Mustacchi
142*0250c53aSRobert Mustacchi if (!oclo_dup3fd("fcntl(FDUP3FD): 0x7777", 0x7777)) {
143*0250c53aSRobert Mustacchi ret = EXIT_FAILURE;
144*0250c53aSRobert Mustacchi }
145*0250c53aSRobert Mustacchi
146*0250c53aSRobert Mustacchi if (!oclo_dup3fd("fcntl(FDUP3FD): FD_CLOEXEC|FD_CLOFORK + 1",
147*0250c53aSRobert Mustacchi (FD_CLOEXEC | FD_CLOFORK) + 1)) {
148*0250c53aSRobert Mustacchi ret = EXIT_FAILURE;
149*0250c53aSRobert Mustacchi }
150*0250c53aSRobert Mustacchi
151*0250c53aSRobert Mustacchi if (!oclo_dup3fd("fcntl(FDUP3FD): INT_MAX", INT_MAX)) {
152*0250c53aSRobert Mustacchi ret = EXIT_FAILURE;
153*0250c53aSRobert Mustacchi }
154*0250c53aSRobert Mustacchi
155*0250c53aSRobert Mustacchi
156*0250c53aSRobert Mustacchi if (!oclo_pipe2("pipe2(): O_RDWR", O_RDWR)) {
157*0250c53aSRobert Mustacchi ret = EXIT_FAILURE;
158*0250c53aSRobert Mustacchi }
159*0250c53aSRobert Mustacchi
160*0250c53aSRobert Mustacchi if (!oclo_pipe2("pipe2(): O_SYNC|O_CLOXEC", O_SYNC | O_CLOEXEC)) {
161*0250c53aSRobert Mustacchi ret = EXIT_FAILURE;
162*0250c53aSRobert Mustacchi }
163*0250c53aSRobert Mustacchi
164*0250c53aSRobert Mustacchi if (!oclo_pipe2("pipe2(): O_CLOFORK|O_WRONLY", O_CLOFORK | O_WRONLY)) {
165*0250c53aSRobert Mustacchi ret = EXIT_FAILURE;
166*0250c53aSRobert Mustacchi }
167*0250c53aSRobert Mustacchi
168*0250c53aSRobert Mustacchi if (!oclo_pipe2("pipe2(): INT32_MAX", INT32_MAX)) {
169*0250c53aSRobert Mustacchi ret = EXIT_FAILURE;
170*0250c53aSRobert Mustacchi }
171*0250c53aSRobert Mustacchi
172*0250c53aSRobert Mustacchi if (!oclo_socket("socket(): INT32_MAX", INT32_MAX)) {
173*0250c53aSRobert Mustacchi ret = EXIT_FAILURE;
174*0250c53aSRobert Mustacchi }
175*0250c53aSRobert Mustacchi
176*0250c53aSRobert Mustacchi if (!oclo_socket("socket(): 3 << 25", 3 << 25)) {
177*0250c53aSRobert Mustacchi ret = EXIT_FAILURE;
178*0250c53aSRobert Mustacchi }
179*0250c53aSRobert Mustacchi
180*0250c53aSRobert Mustacchi if (!oclo_accept("accept4(): INT32_MAX", INT32_MAX)) {
181*0250c53aSRobert Mustacchi ret = EXIT_FAILURE;
182*0250c53aSRobert Mustacchi }
183*0250c53aSRobert Mustacchi
184*0250c53aSRobert Mustacchi if (!oclo_accept("accept4(): 3 << 25", 3 << 25)) {
185*0250c53aSRobert Mustacchi ret = EXIT_FAILURE;
186*0250c53aSRobert Mustacchi }
187*0250c53aSRobert Mustacchi
188*0250c53aSRobert Mustacchi if (ret == EXIT_SUCCESS) {
189*0250c53aSRobert Mustacchi (void) printf("All tests completed successfully\n");
190*0250c53aSRobert Mustacchi }
191*0250c53aSRobert Mustacchi
192*0250c53aSRobert Mustacchi return (ret);
193*0250c53aSRobert Mustacchi }
194