xref: /freebsd/tests/sys/netpfil/pf/ioctl/validation.c (revision 8e748b94e7ac2c476e29a14ad6097388fe7fec27)
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 
541ff545d6SKristof Provost void
551ff545d6SKristof Provost common_init_tbl(struct pfr_table *tbl)
561ff545d6SKristof Provost {
571ff545d6SKristof Provost 	bzero(tbl, sizeof(struct pfr_table));
581ff545d6SKristof Provost 	strcpy(tbl->pfrt_anchor, "anchor");
591ff545d6SKristof Provost 	strcpy(tbl->pfrt_name, "name");
601ff545d6SKristof Provost 	tbl->pfrt_flags = 0;
611ff545d6SKristof Provost 	tbl->pfrt_fback = 0;
621ff545d6SKristof Provost }
631ff545d6SKristof 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 
1341ff545d6SKristof Provost ATF_TC_WITHOUT_HEAD(gettables);
1351ff545d6SKristof Provost ATF_TC_BODY(gettables, tc)
1361ff545d6SKristof Provost {
1371ff545d6SKristof Provost 	struct pfioc_table io;
1381ff545d6SKristof Provost 	struct pfr_table tbl;
1391ff545d6SKristof Provost 	int flags;
1401ff545d6SKristof Provost 
1411ff545d6SKristof Provost 	COMMON_HEAD();
1421ff545d6SKristof Provost 
1431ff545d6SKristof Provost 	flags = 0;
1441ff545d6SKristof Provost 
1451ff545d6SKristof Provost 	bzero(&io, sizeof(io));
1461ff545d6SKristof Provost 	io.pfrio_flags = flags;
1471ff545d6SKristof Provost 	io.pfrio_buffer = &tbl;
1481ff545d6SKristof Provost 	io.pfrio_esize = sizeof(tbl);
1491ff545d6SKristof Provost 
1501ff545d6SKristof Provost 	/* Negative size. This will succeed, because the kernel will not copy
1511ff545d6SKristof Provost 	 * tables than it has. */
1521ff545d6SKristof Provost 	io.pfrio_size = -1;
1531ff545d6SKristof Provost 	if (ioctl(dev, DIOCRGETTABLES, &io) != 0)
1541ff545d6SKristof Provost 		atf_tc_fail("Request with size -1 failed");
1551ff545d6SKristof Provost 
1561ff545d6SKristof Provost 	/* Overly large size. See above. */
1571ff545d6SKristof Provost 	io.pfrio_size = 1 << 24;
1581ff545d6SKristof Provost 	if (ioctl(dev, DIOCRGETTABLES, &io) != 0)
1591ff545d6SKristof Provost 		atf_tc_fail("Request with size 1 << 24 failed");
1601ff545d6SKristof Provost 
1611ff545d6SKristof Provost 	COMMON_CLEANUP();
1621ff545d6SKristof Provost }
1631ff545d6SKristof Provost 
1641ff545d6SKristof Provost ATF_TC_WITHOUT_HEAD(gettstats);
1651ff545d6SKristof Provost ATF_TC_BODY(gettstats, tc)
1661ff545d6SKristof Provost {
1671ff545d6SKristof Provost 	struct pfioc_table io;
1681ff545d6SKristof Provost 	struct pfr_tstats stats;
1691ff545d6SKristof Provost 	int flags;
1701ff545d6SKristof Provost 
1711ff545d6SKristof Provost 	COMMON_HEAD();
1721ff545d6SKristof Provost 
1731ff545d6SKristof Provost 	flags = 0;
1741ff545d6SKristof Provost 
1751ff545d6SKristof Provost 	bzero(&io, sizeof(io));
1761ff545d6SKristof Provost 	io.pfrio_flags = flags;
1771ff545d6SKristof Provost 	io.pfrio_buffer = &stats;
1781ff545d6SKristof Provost 	io.pfrio_esize = sizeof(stats);
1791ff545d6SKristof Provost 
1801ff545d6SKristof Provost 	/* Negative size. This will succeed, because the kernel will not copy
1811ff545d6SKristof Provost 	 * tables than it has. */
1821ff545d6SKristof Provost 	io.pfrio_size = -1;
1831ff545d6SKristof Provost 	if (ioctl(dev, DIOCRGETTSTATS, &io) != 0)
1841ff545d6SKristof Provost 		atf_tc_fail("Request with size -1 failed");
1851ff545d6SKristof Provost 
1861ff545d6SKristof Provost 	/* Overly large size. See above. */
1871ff545d6SKristof Provost 	io.pfrio_size = 1 << 24;
1881ff545d6SKristof Provost 	if (ioctl(dev, DIOCRGETTSTATS, &io) != 0)
1891ff545d6SKristof Provost 		atf_tc_fail("Request with size 1 << 24 failed");
1901ff545d6SKristof Provost 
1911ff545d6SKristof Provost 	COMMON_CLEANUP();
1921ff545d6SKristof Provost }
1931ff545d6SKristof Provost 
1941ff545d6SKristof Provost ATF_TC_WITHOUT_HEAD(clrtstats);
1951ff545d6SKristof Provost ATF_TC_BODY(clrtstats, tc)
1961ff545d6SKristof Provost {
1971ff545d6SKristof Provost 	struct pfioc_table io;
1981ff545d6SKristof Provost 	struct pfr_table tbl;
1991ff545d6SKristof Provost 	int flags;
2001ff545d6SKristof Provost 
2011ff545d6SKristof Provost 	COMMON_HEAD();
2021ff545d6SKristof Provost 
2031ff545d6SKristof Provost 	flags = 0;
2041ff545d6SKristof Provost 
2051ff545d6SKristof Provost 	common_init_tbl(&tbl);
2061ff545d6SKristof Provost 
2071ff545d6SKristof Provost 	bzero(&io, sizeof(io));
2081ff545d6SKristof Provost 	io.pfrio_flags = flags;
2091ff545d6SKristof Provost 	io.pfrio_buffer = &tbl;
2101ff545d6SKristof Provost 	io.pfrio_esize = sizeof(tbl);
2111ff545d6SKristof Provost 
2121ff545d6SKristof Provost 	/* Negative size. This will succeed, because the kernel will not copy
2131ff545d6SKristof Provost 	 * tables than it has. */
2141ff545d6SKristof Provost 	io.pfrio_size = -1;
2151ff545d6SKristof Provost 	if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0)
2161ff545d6SKristof Provost 		atf_tc_fail("Request with size -1 failed ");
2171ff545d6SKristof Provost 
2181ff545d6SKristof Provost 	/* Overly large size. See above. */
2191ff545d6SKristof Provost 	io.pfrio_size = 1 << 24;
2201ff545d6SKristof Provost 	if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0)
2211ff545d6SKristof Provost 		atf_tc_fail("Request with size 1 << 24 failed");
2221ff545d6SKristof Provost 
2231ff545d6SKristof Provost 	COMMON_CLEANUP();
2241ff545d6SKristof Provost }
2251ff545d6SKristof Provost 
2261ff545d6SKristof Provost ATF_TC_WITHOUT_HEAD(settflags);
2271ff545d6SKristof Provost ATF_TC_BODY(settflags, tc)
2281ff545d6SKristof Provost {
2291ff545d6SKristof Provost 	struct pfioc_table io;
2301ff545d6SKristof Provost 	struct pfr_table tbl;
2311ff545d6SKristof Provost 	int flags;
2321ff545d6SKristof Provost 
2331ff545d6SKristof Provost 	COMMON_HEAD();
2341ff545d6SKristof Provost 
2351ff545d6SKristof Provost 	flags = 0;
2361ff545d6SKristof Provost 
2371ff545d6SKristof Provost 	common_init_tbl(&tbl);
2381ff545d6SKristof Provost 
2391ff545d6SKristof Provost 	bzero(&io, sizeof(io));
2401ff545d6SKristof Provost 	io.pfrio_flags = flags;
2411ff545d6SKristof Provost 	io.pfrio_buffer = &tbl;
2421ff545d6SKristof Provost 	io.pfrio_esize = sizeof(tbl);
2431ff545d6SKristof Provost 
2441ff545d6SKristof Provost 	/* Negative size. This will succeed, because the kernel will not copy
2451ff545d6SKristof Provost 	 * tables than it has. */
2461ff545d6SKristof Provost 	io.pfrio_size = -1;
2471ff545d6SKristof Provost 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0)
2481ff545d6SKristof Provost 		atf_tc_fail("Request with size -1 failed");
2491ff545d6SKristof Provost 
2501ff545d6SKristof Provost 	/* Overly large size. See above. */
2511ff545d6SKristof Provost 	io.pfrio_size = 1 << 28;
2521ff545d6SKristof Provost 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0)
2531ff545d6SKristof Provost 		atf_tc_fail("Request with size 1 << 24 failed");
2541ff545d6SKristof Provost 
2551ff545d6SKristof Provost 	COMMON_CLEANUP();
2561ff545d6SKristof Provost }
2571ff545d6SKristof Provost 
258*8e748b94SKristof Provost ATF_TC_WITHOUT_HEAD(igetifaces);
259*8e748b94SKristof Provost ATF_TC_BODY(igetifaces, tc)
260*8e748b94SKristof Provost {
261*8e748b94SKristof Provost 	struct pfioc_iface io;
262*8e748b94SKristof Provost 	struct pfi_kif kif;
263*8e748b94SKristof Provost 
264*8e748b94SKristof Provost 	COMMON_HEAD();
265*8e748b94SKristof Provost 
266*8e748b94SKristof Provost 	bzero(&io, sizeof(io));
267*8e748b94SKristof Provost 	io.pfiio_flags = 0;
268*8e748b94SKristof Provost 	io.pfiio_buffer = &kif;
269*8e748b94SKristof Provost 	io.pfiio_esize = sizeof(kif);
270*8e748b94SKristof Provost 
271*8e748b94SKristof Provost 	/* Negative size */
272*8e748b94SKristof Provost 	io.pfiio_size = -1;
273*8e748b94SKristof Provost 	if (ioctl(dev, DIOCIGETIFACES, &io) == 0)
274*8e748b94SKristof Provost 		atf_tc_fail("request with size -1 succeeded");
275*8e748b94SKristof Provost 
276*8e748b94SKristof Provost 	/* Overflow size */
277*8e748b94SKristof Provost 	io.pfiio_size = 1 << 31;
278*8e748b94SKristof Provost 	if (ioctl(dev, DIOCIGETIFACES, &io) == 0)
279*8e748b94SKristof Provost 		atf_tc_fail("request with size 1 << 31 succeeded");
280*8e748b94SKristof Provost 
281*8e748b94SKristof Provost 	COMMON_CLEANUP();
282*8e748b94SKristof Provost }
283*8e748b94SKristof Provost 
284*8e748b94SKristof Provost ATF_TC_WITHOUT_HEAD(commit);
285*8e748b94SKristof Provost ATF_TC_BODY(commit, tc)
286*8e748b94SKristof Provost {
287*8e748b94SKristof Provost 	struct pfioc_trans io;
288*8e748b94SKristof Provost 	struct pfioc_trans_e ioe;
289*8e748b94SKristof Provost 
290*8e748b94SKristof Provost 	COMMON_HEAD();
291*8e748b94SKristof Provost 
292*8e748b94SKristof Provost 	bzero(&io, sizeof(io));
293*8e748b94SKristof Provost 	io.esize = sizeof(ioe);
294*8e748b94SKristof Provost 	io.array = &ioe;
295*8e748b94SKristof Provost 
296*8e748b94SKristof Provost 	/* Negative size */
297*8e748b94SKristof Provost 	io.size = -1;
298*8e748b94SKristof Provost 	if (ioctl(dev, DIOCXCOMMIT, &io) == 0)
299*8e748b94SKristof Provost 		atf_tc_fail("request with size -1 succeeded");
300*8e748b94SKristof Provost 
301*8e748b94SKristof Provost 	/* Overflow size */
302*8e748b94SKristof Provost 	io.size = 1 << 30;
303*8e748b94SKristof Provost 	if (ioctl(dev, DIOCXCOMMIT, &io) == 0)
304*8e748b94SKristof Provost 		atf_tc_fail("request with size 1 << 30 succeeded");
305*8e748b94SKristof Provost 
306*8e748b94SKristof Provost 	/* NULL buffer */
307*8e748b94SKristof Provost 	io.size = 1;
308*8e748b94SKristof Provost 	io.array = NULL;
309*8e748b94SKristof Provost 	if (ioctl(dev, DIOCXCOMMIT, &io) == 0)
310*8e748b94SKristof Provost 		atf_tc_fail("request with size -1 succeeded");
311*8e748b94SKristof Provost 
312*8e748b94SKristof Provost 	COMMON_CLEANUP();
313*8e748b94SKristof Provost }
314*8e748b94SKristof Provost 
31598c5f988SKristof Provost ATF_TP_ADD_TCS(tp)
31698c5f988SKristof Provost {
31798c5f988SKristof Provost 	ATF_TP_ADD_TC(tp, addtables);
31898c5f988SKristof Provost 	ATF_TP_ADD_TC(tp, deltables);
3191ff545d6SKristof Provost 	ATF_TP_ADD_TC(tp, gettables);
3201ff545d6SKristof Provost 	ATF_TP_ADD_TC(tp, gettstats);
3211ff545d6SKristof Provost 	ATF_TP_ADD_TC(tp, clrtstats);
3221ff545d6SKristof Provost 	ATF_TP_ADD_TC(tp, settflags);
323*8e748b94SKristof Provost 	ATF_TP_ADD_TC(tp, igetifaces);
324*8e748b94SKristof Provost 	ATF_TP_ADD_TC(tp, commit);
32598c5f988SKristof Provost 
32698c5f988SKristof Provost 	return (atf_no_error());
32798c5f988SKristof Provost }
328