xref: /freebsd/tests/sys/netpfil/pf/ioctl/validation.c (revision 1ff545d642ccf36e5b47e5dc5e374f941c89578b)
198c5f988SKristof Provost /*-
298c5f988SKristof Provost  * Copyright (c) 2018	Kristof Provost <kp@FreeBSD.org>
398c5f988SKristof Provost  *
498c5f988SKristof Provost  * Redistribution and use in source and binary forms, with or without
598c5f988SKristof Provost  * modification, are permitted provided that the following conditions
698c5f988SKristof Provost  * are met:
798c5f988SKristof Provost  * 1. Redistributions of source code must retain the above copyright
898c5f988SKristof Provost  *    notice, this list of conditions and the following disclaimer.
998c5f988SKristof Provost  * 2. Redistributions in binary form must reproduce the above copyright
1098c5f988SKristof Provost  *    notice, this list of conditions and the following disclaimer in the
1198c5f988SKristof Provost  *    documentation and/or other materials provided with the distribution.
1298c5f988SKristof Provost  *
1398c5f988SKristof Provost  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1498c5f988SKristof Provost  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1598c5f988SKristof Provost  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1698c5f988SKristof Provost  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1798c5f988SKristof Provost  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1898c5f988SKristof Provost  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1998c5f988SKristof Provost  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2098c5f988SKristof Provost  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2198c5f988SKristof Provost  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2298c5f988SKristof Provost  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2398c5f988SKristof Provost  * SUCH DAMAGE.
2498c5f988SKristof Provost  *
2598c5f988SKristof Provost  * $FreeBSD$
2698c5f988SKristof Provost  */
2798c5f988SKristof Provost 
2898c5f988SKristof Provost #include <sys/param.h>
2998c5f988SKristof Provost #include <sys/module.h>
3098c5f988SKristof Provost #include <sys/types.h>
3198c5f988SKristof Provost #include <sys/ioctl.h>
3298c5f988SKristof Provost #include <sys/socket.h>
3398c5f988SKristof Provost 
3498c5f988SKristof Provost #include <net/if.h>
3598c5f988SKristof Provost #include <net/pfvar.h>
3698c5f988SKristof Provost 
3798c5f988SKristof Provost #include <fcntl.h>
3898c5f988SKristof Provost #include <stdio.h>
3998c5f988SKristof Provost 
4098c5f988SKristof Provost #include <atf-c.h>
4198c5f988SKristof Provost 
4298c5f988SKristof Provost static int dev;
4398c5f988SKristof Provost 
4498c5f988SKristof Provost #define COMMON_HEAD() \
4598c5f988SKristof Provost 	if (modfind("pf") == -1) \
4698c5f988SKristof Provost 		atf_tc_skip("pf not loaded"); \
4798c5f988SKristof Provost 	dev = open("/dev/pf", O_RDWR); \
4898c5f988SKristof Provost 	if (dev == -1) \
4998c5f988SKristof Provost 		atf_tc_skip("Failed to open /dev/pf");
5098c5f988SKristof Provost 
5198c5f988SKristof Provost #define COMMON_CLEANUP() \
5298c5f988SKristof Provost 	close(dev);
5398c5f988SKristof Provost 
54*1ff545d6SKristof Provost void
55*1ff545d6SKristof Provost common_init_tbl(struct pfr_table *tbl)
56*1ff545d6SKristof Provost {
57*1ff545d6SKristof Provost 	bzero(tbl, sizeof(struct pfr_table));
58*1ff545d6SKristof Provost 	strcpy(tbl->pfrt_anchor, "anchor");
59*1ff545d6SKristof Provost 	strcpy(tbl->pfrt_name, "name");
60*1ff545d6SKristof Provost 	tbl->pfrt_flags = 0;
61*1ff545d6SKristof Provost 	tbl->pfrt_fback = 0;
62*1ff545d6SKristof Provost }
63*1ff545d6SKristof Provost 
6498c5f988SKristof Provost ATF_TC_WITHOUT_HEAD(addtables);
6598c5f988SKristof Provost ATF_TC_BODY(addtables, tc)
6698c5f988SKristof Provost {
6798c5f988SKristof Provost 	struct pfioc_table io;
6898c5f988SKristof Provost 	struct pfr_table tbl;
6998c5f988SKristof Provost 	int flags;
7098c5f988SKristof Provost 
7198c5f988SKristof Provost 	COMMON_HEAD();
7298c5f988SKristof Provost 
7398c5f988SKristof Provost 	flags = 0;
7498c5f988SKristof Provost 
7598c5f988SKristof Provost 	bzero(&io, sizeof(io));
7698c5f988SKristof Provost 	io.pfrio_flags = flags;
7798c5f988SKristof Provost 	io.pfrio_buffer = &tbl;
7898c5f988SKristof Provost 	io.pfrio_esize = sizeof(tbl);
7998c5f988SKristof Provost 
8098c5f988SKristof Provost 	/* Negative size */
8198c5f988SKristof Provost 	io.pfrio_size = -1;
8298c5f988SKristof Provost 	if (ioctl(dev, DIOCRADDTABLES, &io) == 0)
8398c5f988SKristof Provost 		atf_tc_fail("Request with size -1 succeeded");
8498c5f988SKristof Provost 
8598c5f988SKristof Provost 	/* Overly large size */
8698c5f988SKristof Provost 	io.pfrio_size = 1 << 24;
8798c5f988SKristof Provost 	if (ioctl(dev, DIOCRADDTABLES, &io) == 0)
8898c5f988SKristof Provost 		atf_tc_fail("Request with size 1 << 24 succeeded");
8998c5f988SKristof Provost 
9098c5f988SKristof Provost 	/* NULL buffer */
9198c5f988SKristof Provost 	io.pfrio_size = 1;
9298c5f988SKristof Provost 	io.pfrio_buffer = NULL;
9398c5f988SKristof Provost 	if (ioctl(dev, DIOCRADDTABLES, &io) == 0)
9498c5f988SKristof Provost 		atf_tc_fail("Request with NULL buffer succeeded");
9598c5f988SKristof Provost 
9698c5f988SKristof Provost 	COMMON_CLEANUP();
9798c5f988SKristof Provost }
9898c5f988SKristof Provost 
9998c5f988SKristof Provost ATF_TC_WITHOUT_HEAD(deltables);
10098c5f988SKristof Provost ATF_TC_BODY(deltables, tc)
10198c5f988SKristof Provost {
10298c5f988SKristof Provost 	struct pfioc_table io;
10398c5f988SKristof Provost 	struct pfr_table tbl;
10498c5f988SKristof Provost 	int flags;
10598c5f988SKristof Provost 
10698c5f988SKristof Provost 	COMMON_HEAD();
10798c5f988SKristof Provost 
10898c5f988SKristof Provost 	flags = 0;
10998c5f988SKristof Provost 
11098c5f988SKristof Provost 	bzero(&io, sizeof(io));
11198c5f988SKristof Provost 	io.pfrio_flags = flags;
11298c5f988SKristof Provost 	io.pfrio_buffer = &tbl;
11398c5f988SKristof Provost 	io.pfrio_esize = sizeof(tbl);
11498c5f988SKristof Provost 
11598c5f988SKristof Provost 	/* Negative size */
11698c5f988SKristof Provost 	io.pfrio_size = -1;
11798c5f988SKristof Provost 	if (ioctl(dev, DIOCRDELTABLES, &io) == 0)
11898c5f988SKristof Provost 		atf_tc_fail("Request with size -1 succeeded");
11998c5f988SKristof Provost 
12098c5f988SKristof Provost 	/* Overly large size */
12198c5f988SKristof Provost 	io.pfrio_size = 1 << 24;
12298c5f988SKristof Provost 	if (ioctl(dev, DIOCRDELTABLES, &io) == 0)
12398c5f988SKristof Provost 		atf_tc_fail("Request with size 1 << 24 succeeded");
12498c5f988SKristof Provost 
12598c5f988SKristof Provost 	/* NULL buffer */
12698c5f988SKristof Provost 	io.pfrio_size = 1;
12798c5f988SKristof Provost 	io.pfrio_buffer = NULL;
12898c5f988SKristof Provost 	if (ioctl(dev, DIOCRDELTABLES, &io) == 0)
12998c5f988SKristof Provost 		atf_tc_fail("Request with NULL buffer succeeded");
13098c5f988SKristof Provost 
13198c5f988SKristof Provost 	COMMON_CLEANUP();
13298c5f988SKristof Provost }
13398c5f988SKristof Provost 
134*1ff545d6SKristof Provost ATF_TC_WITHOUT_HEAD(gettables);
135*1ff545d6SKristof Provost ATF_TC_BODY(gettables, tc)
136*1ff545d6SKristof Provost {
137*1ff545d6SKristof Provost 	struct pfioc_table io;
138*1ff545d6SKristof Provost 	struct pfr_table tbl;
139*1ff545d6SKristof Provost 	int flags;
140*1ff545d6SKristof Provost 
141*1ff545d6SKristof Provost 	COMMON_HEAD();
142*1ff545d6SKristof Provost 
143*1ff545d6SKristof Provost 	flags = 0;
144*1ff545d6SKristof Provost 
145*1ff545d6SKristof Provost 	bzero(&io, sizeof(io));
146*1ff545d6SKristof Provost 	io.pfrio_flags = flags;
147*1ff545d6SKristof Provost 	io.pfrio_buffer = &tbl;
148*1ff545d6SKristof Provost 	io.pfrio_esize = sizeof(tbl);
149*1ff545d6SKristof Provost 
150*1ff545d6SKristof Provost 	/* Negative size. This will succeed, because the kernel will not copy
151*1ff545d6SKristof Provost 	 * tables than it has. */
152*1ff545d6SKristof Provost 	io.pfrio_size = -1;
153*1ff545d6SKristof Provost 	if (ioctl(dev, DIOCRGETTABLES, &io) != 0)
154*1ff545d6SKristof Provost 		atf_tc_fail("Request with size -1 failed");
155*1ff545d6SKristof Provost 
156*1ff545d6SKristof Provost 	/* Overly large size. See above. */
157*1ff545d6SKristof Provost 	io.pfrio_size = 1 << 24;
158*1ff545d6SKristof Provost 	if (ioctl(dev, DIOCRGETTABLES, &io) != 0)
159*1ff545d6SKristof Provost 		atf_tc_fail("Request with size 1 << 24 failed");
160*1ff545d6SKristof Provost 
161*1ff545d6SKristof Provost 	COMMON_CLEANUP();
162*1ff545d6SKristof Provost }
163*1ff545d6SKristof Provost 
164*1ff545d6SKristof Provost ATF_TC_WITHOUT_HEAD(gettstats);
165*1ff545d6SKristof Provost ATF_TC_BODY(gettstats, tc)
166*1ff545d6SKristof Provost {
167*1ff545d6SKristof Provost 	struct pfioc_table io;
168*1ff545d6SKristof Provost 	struct pfr_tstats stats;
169*1ff545d6SKristof Provost 	int flags;
170*1ff545d6SKristof Provost 
171*1ff545d6SKristof Provost 	COMMON_HEAD();
172*1ff545d6SKristof Provost 
173*1ff545d6SKristof Provost 	flags = 0;
174*1ff545d6SKristof Provost 
175*1ff545d6SKristof Provost 	bzero(&io, sizeof(io));
176*1ff545d6SKristof Provost 	io.pfrio_flags = flags;
177*1ff545d6SKristof Provost 	io.pfrio_buffer = &stats;
178*1ff545d6SKristof Provost 	io.pfrio_esize = sizeof(stats);
179*1ff545d6SKristof Provost 
180*1ff545d6SKristof Provost 	/* Negative size. This will succeed, because the kernel will not copy
181*1ff545d6SKristof Provost 	 * tables than it has. */
182*1ff545d6SKristof Provost 	io.pfrio_size = -1;
183*1ff545d6SKristof Provost 	if (ioctl(dev, DIOCRGETTSTATS, &io) != 0)
184*1ff545d6SKristof Provost 		atf_tc_fail("Request with size -1 failed");
185*1ff545d6SKristof Provost 
186*1ff545d6SKristof Provost 	/* Overly large size. See above. */
187*1ff545d6SKristof Provost 	io.pfrio_size = 1 << 24;
188*1ff545d6SKristof Provost 	if (ioctl(dev, DIOCRGETTSTATS, &io) != 0)
189*1ff545d6SKristof Provost 		atf_tc_fail("Request with size 1 << 24 failed");
190*1ff545d6SKristof Provost 
191*1ff545d6SKristof Provost 	COMMON_CLEANUP();
192*1ff545d6SKristof Provost }
193*1ff545d6SKristof Provost 
194*1ff545d6SKristof Provost ATF_TC_WITHOUT_HEAD(clrtstats);
195*1ff545d6SKristof Provost ATF_TC_BODY(clrtstats, tc)
196*1ff545d6SKristof Provost {
197*1ff545d6SKristof Provost 	struct pfioc_table io;
198*1ff545d6SKristof Provost 	struct pfr_table tbl;
199*1ff545d6SKristof Provost 	int flags;
200*1ff545d6SKristof Provost 
201*1ff545d6SKristof Provost 	COMMON_HEAD();
202*1ff545d6SKristof Provost 
203*1ff545d6SKristof Provost 	flags = 0;
204*1ff545d6SKristof Provost 
205*1ff545d6SKristof Provost 	common_init_tbl(&tbl);
206*1ff545d6SKristof Provost 
207*1ff545d6SKristof Provost 	bzero(&io, sizeof(io));
208*1ff545d6SKristof Provost 	io.pfrio_flags = flags;
209*1ff545d6SKristof Provost 	io.pfrio_buffer = &tbl;
210*1ff545d6SKristof Provost 	io.pfrio_esize = sizeof(tbl);
211*1ff545d6SKristof Provost 
212*1ff545d6SKristof Provost 	/* Negative size. This will succeed, because the kernel will not copy
213*1ff545d6SKristof Provost 	 * tables than it has. */
214*1ff545d6SKristof Provost 	io.pfrio_size = -1;
215*1ff545d6SKristof Provost 	if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0)
216*1ff545d6SKristof Provost 		atf_tc_fail("Request with size -1 failed ");
217*1ff545d6SKristof Provost 
218*1ff545d6SKristof Provost 	/* Overly large size. See above. */
219*1ff545d6SKristof Provost 	io.pfrio_size = 1 << 24;
220*1ff545d6SKristof Provost 	if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0)
221*1ff545d6SKristof Provost 		atf_tc_fail("Request with size 1 << 24 failed");
222*1ff545d6SKristof Provost 
223*1ff545d6SKristof Provost 	COMMON_CLEANUP();
224*1ff545d6SKristof Provost }
225*1ff545d6SKristof Provost 
226*1ff545d6SKristof Provost ATF_TC_WITHOUT_HEAD(settflags);
227*1ff545d6SKristof Provost ATF_TC_BODY(settflags, tc)
228*1ff545d6SKristof Provost {
229*1ff545d6SKristof Provost 	struct pfioc_table io;
230*1ff545d6SKristof Provost 	struct pfr_table tbl;
231*1ff545d6SKristof Provost 	int flags;
232*1ff545d6SKristof Provost 
233*1ff545d6SKristof Provost 	COMMON_HEAD();
234*1ff545d6SKristof Provost 
235*1ff545d6SKristof Provost 	flags = 0;
236*1ff545d6SKristof Provost 
237*1ff545d6SKristof Provost 	common_init_tbl(&tbl);
238*1ff545d6SKristof Provost 
239*1ff545d6SKristof Provost 	bzero(&io, sizeof(io));
240*1ff545d6SKristof Provost 	io.pfrio_flags = flags;
241*1ff545d6SKristof Provost 	io.pfrio_buffer = &tbl;
242*1ff545d6SKristof Provost 	io.pfrio_esize = sizeof(tbl);
243*1ff545d6SKristof Provost 
244*1ff545d6SKristof Provost 	/* Negative size. This will succeed, because the kernel will not copy
245*1ff545d6SKristof Provost 	 * tables than it has. */
246*1ff545d6SKristof Provost 	io.pfrio_size = -1;
247*1ff545d6SKristof Provost 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0)
248*1ff545d6SKristof Provost 		atf_tc_fail("Request with size -1 failed");
249*1ff545d6SKristof Provost 
250*1ff545d6SKristof Provost 	/* Overly large size. See above. */
251*1ff545d6SKristof Provost 	io.pfrio_size = 1 << 28;
252*1ff545d6SKristof Provost 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0)
253*1ff545d6SKristof Provost 		atf_tc_fail("Request with size 1 << 24 failed");
254*1ff545d6SKristof Provost 
255*1ff545d6SKristof Provost 	COMMON_CLEANUP();
256*1ff545d6SKristof Provost }
257*1ff545d6SKristof Provost 
25898c5f988SKristof Provost ATF_TP_ADD_TCS(tp)
25998c5f988SKristof Provost {
26098c5f988SKristof Provost 	ATF_TP_ADD_TC(tp, addtables);
26198c5f988SKristof Provost 	ATF_TP_ADD_TC(tp, deltables);
262*1ff545d6SKristof Provost 	ATF_TP_ADD_TC(tp, gettables);
263*1ff545d6SKristof Provost 	ATF_TP_ADD_TC(tp, gettstats);
264*1ff545d6SKristof Provost 	ATF_TP_ADD_TC(tp, clrtstats);
265*1ff545d6SKristof Provost 	ATF_TP_ADD_TC(tp, settflags);
26698c5f988SKristof Provost 
26798c5f988SKristof Provost 	return (atf_no_error());
26898c5f988SKristof Provost }
269