mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-15 10:17:20 +00:00
pf: Fix deadlock with route-to
If a locally generated packet is routed (with route-to/reply-to/dup-to) out of a different interface it's passed through the firewall again. This meant we lost the inp pointer and if we required the pointer (e.g. for user ID matching) we'd deadlock trying to acquire an inp lock we've already got. Pass the inp pointer along with pf_route()/pf_route6(). PR: 228782 MFC after: 1 week
This commit is contained in:
parent
44bcc06816
commit
0b799353d8
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=334876
@ -295,14 +295,14 @@ static void pf_mtag_free(struct m_tag *);
|
||||
#ifdef INET
|
||||
static void pf_route(struct mbuf **, struct pf_rule *, int,
|
||||
struct ifnet *, struct pf_state *,
|
||||
struct pf_pdesc *);
|
||||
struct pf_pdesc *, struct inpcb *);
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
static void pf_change_a6(struct pf_addr *, u_int16_t *,
|
||||
struct pf_addr *, u_int8_t);
|
||||
static void pf_route6(struct mbuf **, struct pf_rule *, int,
|
||||
struct ifnet *, struct pf_state *,
|
||||
struct pf_pdesc *);
|
||||
struct pf_pdesc *, struct inpcb *);
|
||||
#endif /* INET6 */
|
||||
|
||||
int in4_cksum(struct mbuf *m, u_int8_t nxt, int off, int len);
|
||||
@ -5442,7 +5442,7 @@ pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif,
|
||||
#ifdef INET
|
||||
static void
|
||||
pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
|
||||
struct pf_state *s, struct pf_pdesc *pd)
|
||||
struct pf_state *s, struct pf_pdesc *pd, struct inpcb *inp)
|
||||
{
|
||||
struct mbuf *m0, *m1;
|
||||
struct sockaddr_in dst;
|
||||
@ -5510,7 +5510,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
|
||||
goto bad;
|
||||
|
||||
if (oifp != ifp) {
|
||||
if (pf_test(PF_OUT, 0, ifp, &m0, NULL) != PF_PASS)
|
||||
if (pf_test(PF_OUT, 0, ifp, &m0, inp) != PF_PASS)
|
||||
goto bad;
|
||||
else if (m0 == NULL)
|
||||
goto done;
|
||||
@ -5603,7 +5603,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
|
||||
#ifdef INET6
|
||||
static void
|
||||
pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
|
||||
struct pf_state *s, struct pf_pdesc *pd)
|
||||
struct pf_state *s, struct pf_pdesc *pd, struct inpcb *inp)
|
||||
{
|
||||
struct mbuf *m0;
|
||||
struct sockaddr_in6 dst;
|
||||
@ -5672,7 +5672,7 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
|
||||
goto bad;
|
||||
|
||||
if (oifp != ifp) {
|
||||
if (pf_test6(PF_OUT, PFIL_FWD, ifp, &m0, NULL) != PF_PASS)
|
||||
if (pf_test6(PF_OUT, PFIL_FWD, ifp, &m0, inp) != PF_PASS)
|
||||
goto bad;
|
||||
else if (m0 == NULL)
|
||||
goto done;
|
||||
@ -6236,7 +6236,7 @@ pf_test(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb *
|
||||
default:
|
||||
/* pf_route() returns unlocked. */
|
||||
if (r->rt) {
|
||||
pf_route(m0, r, dir, kif->pfik_ifp, s, &pd);
|
||||
pf_route(m0, r, dir, kif->pfik_ifp, s, &pd, inp);
|
||||
return (action);
|
||||
}
|
||||
break;
|
||||
@ -6633,7 +6633,7 @@ pf_test6(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb
|
||||
default:
|
||||
/* pf_route6() returns unlocked. */
|
||||
if (r->rt) {
|
||||
pf_route6(m0, r, dir, kif->pfik_ifp, s, &pd);
|
||||
pf_route6(m0, r, dir, kif->pfik_ifp, s, &pd, inp);
|
||||
return (action);
|
||||
}
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user