From: mbuhl Date: Sun, 26 Jun 2022 11:37:08 +0000 (+0000) Subject: Allow waiting during ktable allocation in pf_ioctl. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=30d709c8a85cb6e091ed98efee6889d483b0b544;p=openbsd Allow waiting during ktable allocation in pf_ioctl. OK bluhm Reported-by: syzbot+50ea4f33ed5dd9264918@syzkaller.appspotmail.com Reported-by: syzbot+df65f8b7ee8c0089e885@syzkaller.appspotmail.com --- diff --git a/sys/net/pf.c b/sys/net/pf.c index cff5528294b..aab01c212de 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.1133 2022/06/13 12:48:00 henning Exp $ */ +/* $OpenBSD: pf.c,v 1.1134 2022/06/26 11:37:08 mbuhl Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -1585,11 +1585,11 @@ pf_purge_expired_states(u_int32_t maxcheck) } int -pf_tbladdr_setup(struct pf_ruleset *rs, struct pf_addr_wrap *aw) +pf_tbladdr_setup(struct pf_ruleset *rs, struct pf_addr_wrap *aw, int wait) { if (aw->type != PF_ADDR_TABLE) return (0); - if ((aw->p.tbl = pfr_attach_table(rs, aw->v.tblname, 1)) == NULL) + if ((aw->p.tbl = pfr_attach_table(rs, aw->v.tblname, wait)) == NULL) return (1); return (0); } diff --git a/sys/net/pf_if.c b/sys/net/pf_if.c index dd1b11d44af..e23c14e6769 100644 --- a/sys/net/pf_if.c +++ b/sys/net/pf_if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_if.c,v 1.105 2022/05/16 13:31:19 bluhm Exp $ */ +/* $OpenBSD: pf_if.c,v 1.106 2022/06/26 11:37:08 mbuhl Exp $ */ /* * Copyright 2005 Henning Brauer @@ -423,7 +423,7 @@ pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af) } int -pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af) +pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af, int wait) { struct pfi_dynaddr *dyn; char tblname[PF_TABLE_NAME_SIZE]; @@ -432,8 +432,7 @@ pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af) if (aw->type != PF_ADDR_DYNIFTL) return (0); - if ((dyn = pool_get(&pfi_addr_pl, PR_WAITOK | PR_LIMITFAIL | PR_ZERO)) - == NULL) + if ((dyn = pool_get(&pfi_addr_pl, wait|PR_LIMITFAIL|PR_ZERO)) == NULL) return (1); if (!strcmp(aw->v.ifname, "self")) @@ -466,7 +465,7 @@ pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af) goto _bad; } - if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname, 1)) == NULL) { + if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname, wait)) == NULL) { rv = 1; goto _bad; } diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c index c055fc6f0e5..a81d8a7876c 100644 --- a/sys/net/pf_ioctl.c +++ b/sys/net/pf_ioctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_ioctl.c,v 1.381 2022/05/10 23:12:25 sashan Exp $ */ +/* $OpenBSD: pf_ioctl.c,v 1.382 2022/06/26 11:37:08 mbuhl Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -891,8 +891,8 @@ int pf_addr_setup(struct pf_ruleset *ruleset, struct pf_addr_wrap *addr, sa_family_t af) { - if (pfi_dynaddr_setup(addr, af) || - pf_tbladdr_setup(ruleset, addr) || + if (pfi_dynaddr_setup(addr, af, PR_WAITOK) || + pf_tbladdr_setup(ruleset, addr, PR_WAITOK) || pf_rtlabel_add(addr)) return (EINVAL); @@ -1413,7 +1413,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) if (rule->overload_tblname[0]) { if ((rule->overload_tbl = pfr_attach_table(ruleset, - rule->overload_tblname, 0)) == NULL) + rule->overload_tblname, PR_WAITOK)) == NULL) error = EINVAL; else rule->overload_tbl->pfrkt_flags |= PFR_TFLAG_ACTIVE; @@ -1636,7 +1636,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) if (newrule->overload_tblname[0]) { newrule->overload_tbl = pfr_attach_table( - ruleset, newrule->overload_tblname, 0); + ruleset, newrule->overload_tblname, + PR_WAITOK); if (newrule->overload_tbl == NULL) error = EINVAL; else diff --git a/sys/net/pf_table.c b/sys/net/pf_table.c index c40505675bd..f537aac2387 100644 --- a/sys/net/pf_table.c +++ b/sys/net/pf_table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_table.c,v 1.142 2022/06/16 20:47:26 sashan Exp $ */ +/* $OpenBSD: pf_table.c,v 1.143 2022/06/26 11:37:08 mbuhl Exp $ */ /* * Copyright (c) 2002 Cedric Berger @@ -323,7 +323,7 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) return (EINVAL); tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0, - !(flags & PFR_FLAG_USERIOCTL)); + (flags & PFR_FLAG_USERIOCTL? PR_WAITOK : PR_NOWAIT)); if (tmpkt == NULL) return (ENOMEM); SLIST_INIT(&workq); @@ -540,7 +540,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, if (kt->pfrkt_flags & PFR_TFLAG_CONST) return (EPERM); tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0, - !(flags & PFR_FLAG_USERIOCTL)); + (flags & PFR_FLAG_USERIOCTL? PR_WAITOK : PR_NOWAIT)); if (tmpkt == NULL) return (ENOMEM); pfr_mark_addrs(kt); @@ -1513,7 +1513,7 @@ pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags) senderr(EINVAL); key.pfrkt_flags |= PFR_TFLAG_ACTIVE; p = pfr_create_ktable(&key.pfrkt_t, tzero, 0, - !(flags & PFR_FLAG_USERIOCTL)); + (flags & PFR_FLAG_USERIOCTL? PR_WAITOK : PR_NOWAIT)); if (p == NULL) senderr(ENOMEM); @@ -1524,7 +1524,7 @@ pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags) key.pfrkt_flags = 0; memset(key.pfrkt_anchor, 0, sizeof(key.pfrkt_anchor)); p->pfrkt_root = pfr_create_ktable(&key.pfrkt_t, 0, 0, - !(flags & PFR_FLAG_USERIOCTL)); + (flags & PFR_FLAG_USERIOCTL? PR_WAITOK : PR_NOWAIT)); if (p->pfrkt_root == NULL) { pfr_destroy_ktable(p, 0); senderr(ENOMEM); @@ -1910,7 +1910,7 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size, kt = RB_FIND(pfr_ktablehead, &pfr_ktables, (struct pfr_ktable *)tbl); if (kt == NULL) { kt = pfr_create_ktable(tbl, 0, 1, - !(flags & PFR_FLAG_USERIOCTL)); + (flags & PFR_FLAG_USERIOCTL? PR_WAITOK : PR_NOWAIT)); if (kt == NULL) return (ENOMEM); SLIST_INSERT_HEAD(&tableq, kt, pfrkt_workq); @@ -1927,7 +1927,7 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size, goto _skip; } rt = pfr_create_ktable(&key.pfrkt_t, 0, 1, - !(flags & PFR_FLAG_USERIOCTL)); + (flags & PFR_FLAG_USERIOCTL? PR_WAITOK : PR_NOWAIT)); if (rt == NULL) { pfr_destroy_ktables(&tableq, 0); return (ENOMEM); @@ -1937,7 +1937,8 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size, } else if (!(kt->pfrkt_flags & PFR_TFLAG_INACTIVE)) xadd++; _skip: - shadow = pfr_create_ktable(tbl, 0, 0, !(flags & PFR_FLAG_USERIOCTL)); + shadow = pfr_create_ktable(tbl, 0, 0, + (flags & PFR_FLAG_USERIOCTL? PR_WAITOK : PR_NOWAIT)); if (shadow == NULL) { pfr_destroy_ktables(&tableq, 0); return (ENOMEM); @@ -2286,15 +2287,12 @@ pfr_clstats_ktable(struct pfr_ktable *kt, time_t tzero, int recurse) struct pfr_ktable * pfr_create_ktable(struct pfr_table *tbl, time_t tzero, int attachruleset, - int intr) + int wait) { struct pfr_ktable *kt; struct pf_ruleset *rs; - if (intr) - kt = pool_get(&pfr_ktable_pl, PR_NOWAIT|PR_ZERO|PR_LIMITFAIL); - else - kt = pool_get(&pfr_ktable_pl, PR_WAITOK|PR_ZERO|PR_LIMITFAIL); + kt = pool_get(&pfr_ktable_pl, wait|PR_ZERO|PR_LIMITFAIL); if (kt == NULL) return (NULL); kt->pfrkt_t = *tbl; @@ -2533,7 +2531,7 @@ pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, struct pf_pdesc *pd, } struct pfr_ktable * -pfr_attach_table(struct pf_ruleset *rs, char *name, int intr) +pfr_attach_table(struct pf_ruleset *rs, char *name, int wait) { struct pfr_ktable *kt, *rt; struct pfr_table tbl; @@ -2545,14 +2543,14 @@ pfr_attach_table(struct pf_ruleset *rs, char *name, int intr) strlcpy(tbl.pfrt_anchor, ac->path, sizeof(tbl.pfrt_anchor)); kt = pfr_lookup_table(&tbl); if (kt == NULL) { - kt = pfr_create_ktable(&tbl, gettime(), 1, intr); + kt = pfr_create_ktable(&tbl, gettime(), 1, wait); if (kt == NULL) return (NULL); if (ac != NULL) { bzero(tbl.pfrt_anchor, sizeof(tbl.pfrt_anchor)); rt = pfr_lookup_table(&tbl); if (rt == NULL) { - rt = pfr_create_ktable(&tbl, 0, 1, intr); + rt = pfr_create_ktable(&tbl, 0, 1, wait); if (rt == NULL) { pfr_destroy_ktable(kt, 0); return (NULL); diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 93394e6da5c..67c27abd4b3 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.507 2022/04/29 09:55:43 mbuhl Exp $ */ +/* $OpenBSD: pfvar.h,v 1.508 2022/06/26 11:37:08 mbuhl Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -1709,7 +1709,7 @@ extern struct ifnet *sync_ifp; extern struct pf_rule pf_default_rule; extern int pf_tbladdr_setup(struct pf_ruleset *, - struct pf_addr_wrap *); + struct pf_addr_wrap *, int); extern void pf_tbladdr_remove(struct pf_addr_wrap *); extern void pf_tbladdr_copyout(struct pf_addr_wrap *); extern void pf_calc_skip_steps(struct pf_rulequeue *); @@ -1875,7 +1875,7 @@ void pfi_group_addmember(const char *); void pfi_group_delmember(const char *); int pfi_match_addr(struct pfi_dynaddr *, struct pf_addr *, sa_family_t); -int pfi_dynaddr_setup(struct pf_addr_wrap *, sa_family_t); +int pfi_dynaddr_setup(struct pf_addr_wrap *, sa_family_t, int); void pfi_dynaddr_remove(struct pf_addr_wrap *); void pfi_dynaddr_copyout(struct pf_addr_wrap *); void pfi_update_status(const char *, struct pf_status *);