aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey V. Elsukov <ae@FreeBSD.org>2017-07-31 11:04:35 +0000
committerAndrey V. Elsukov <ae@FreeBSD.org>2017-07-31 11:04:35 +0000
commit1a01e0e7acfa046443218f190a5bf4d90b732894 (patch)
tree976a401c917ccddb5a0933d3f59f954904f515d9
parent1336f0f4ae443da80cea410bc61dcf113adfe550 (diff)
downloadsrc-1a01e0e7acfa046443218f190a5bf4d90b732894.tar.gz
src-1a01e0e7acfa046443218f190a5bf4d90b732894.zip
Add inpcb pointer to struct ipsec_ctx_data and pass it to the pfil hook
from enc_hhook(). This should solve the problem when pf is used with if_enc(4) interface, and outbound packet with existing PCB checked by pf, and this leads to deadlock due to pf does its own PCB lookup and tries to take rlock when wlock is already held. Now we pass PCB pointer if it is known to the pfil hook, this helps to avoid extra PCB lookup and thus rlock acquiring is not needed. For inbound packets it is safe to pass NULL, because we do not held any PCB locks yet. PR: 220217 MFC after: 3 weeks Sponsored by: Yandex LLC
Notes
Notes: svn path=/head/; revision=321779
-rw-r--r--sys/net/if_enc.c2
-rw-r--r--sys/net/if_enc.h1
-rw-r--r--sys/netipsec/ipsec.h3
-rw-r--r--sys/netipsec/ipsec_input.c8
-rw-r--r--sys/netipsec/ipsec_output.c24
5 files changed, 22 insertions, 16 deletions
diff --git a/sys/net/if_enc.c b/sys/net/if_enc.c
index 1f3ef8f67c04..1d86a087fb82 100644
--- a/sys/net/if_enc.c
+++ b/sys/net/if_enc.c
@@ -284,7 +284,7 @@ enc_hhook(int32_t hhook_type, int32_t hhook_id, void *udata, void *ctx_data,
/* Make a packet looks like it was received on enc(4) */
rcvif = (*ctx->mp)->m_pkthdr.rcvif;
(*ctx->mp)->m_pkthdr.rcvif = ifp;
- if (pfil_run_hooks(ph, ctx->mp, ifp, pdir, NULL) != 0 ||
+ if (pfil_run_hooks(ph, ctx->mp, ifp, pdir, ctx->inp) != 0 ||
*ctx->mp == NULL) {
*ctx->mp = NULL; /* consumed by filter */
return (EACCES);
diff --git a/sys/net/if_enc.h b/sys/net/if_enc.h
index 941ed12a1b69..616c621f2162 100644
--- a/sys/net/if_enc.h
+++ b/sys/net/if_enc.h
@@ -33,6 +33,7 @@
struct ipsec_ctx_data {
struct mbuf **mp;
struct secasvar *sav;
+ struct inpcb *inp;
uint8_t af;
#define IPSEC_ENC_BEFORE 0x01
#define IPSEC_ENC_AFTER 0x02
diff --git a/sys/netipsec/ipsec.h b/sys/netipsec/ipsec.h
index 147412f980e0..429e1c49114e 100644
--- a/sys/netipsec/ipsec.h
+++ b/sys/netipsec/ipsec.h
@@ -253,8 +253,9 @@ struct ipsecstat {
#include <sys/counter.h>
struct ipsec_ctx_data;
-#define IPSEC_INIT_CTX(_ctx, _mp, _sav, _af, _enc) do { \
+#define IPSEC_INIT_CTX(_ctx, _mp, _inp, _sav, _af, _enc) do { \
(_ctx)->mp = (_mp); \
+ (_ctx)->inp = (_inp); \
(_ctx)->sav = (_sav); \
(_ctx)->af = (_af); \
(_ctx)->enc = (_enc); \
diff --git a/sys/netipsec/ipsec_input.c b/sys/netipsec/ipsec_input.c
index f30a017be146..9814495f7d6f 100644
--- a/sys/netipsec/ipsec_input.c
+++ b/sys/netipsec/ipsec_input.c
@@ -325,7 +325,7 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
(prot == IPPROTO_UDP || prot == IPPROTO_TCP))
udp_ipsec_adjust_cksum(m, sav, prot, skip);
- IPSEC_INIT_CTX(&ctx, &m, sav, AF_INET, IPSEC_ENC_BEFORE);
+ IPSEC_INIT_CTX(&ctx, &m, NULL, sav, AF_INET, IPSEC_ENC_BEFORE);
if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0)
goto bad;
ip = mtod(m, struct ip *); /* update pointer */
@@ -416,7 +416,7 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
goto bad;
}
- IPSEC_INIT_CTX(&ctx, &m, sav, af, IPSEC_ENC_AFTER);
+ IPSEC_INIT_CTX(&ctx, &m, NULL, sav, af, IPSEC_ENC_AFTER);
if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0)
goto bad;
@@ -522,7 +522,7 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
goto bad;
}
- IPSEC_INIT_CTX(&ctx, &m, sav, af, IPSEC_ENC_BEFORE);
+ IPSEC_INIT_CTX(&ctx, &m, NULL, sav, af, IPSEC_ENC_BEFORE);
if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0)
goto bad;
@@ -593,7 +593,7 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
else
#endif
af = AF_INET6;
- IPSEC_INIT_CTX(&ctx, &m, sav, af, IPSEC_ENC_AFTER);
+ IPSEC_INIT_CTX(&ctx, &m, NULL, sav, af, IPSEC_ENC_AFTER);
if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0)
goto bad;
if (skip == 0) {
diff --git a/sys/netipsec/ipsec_output.c b/sys/netipsec/ipsec_output.c
index ee45ce208744..e36a70a433d5 100644
--- a/sys/netipsec/ipsec_output.c
+++ b/sys/netipsec/ipsec_output.c
@@ -181,7 +181,8 @@ next:
* IPsec output logic for IPv4.
*/
static int
-ipsec4_perform_request(struct mbuf *m, struct secpolicy *sp, u_int idx)
+ipsec4_perform_request(struct mbuf *m, struct secpolicy *sp,
+ struct inpcb *inp, u_int idx)
{
struct ipsec_ctx_data ctx;
union sockaddr_union *dst;
@@ -211,7 +212,7 @@ ipsec4_perform_request(struct mbuf *m, struct secpolicy *sp, u_int idx)
/*
* XXXAE: most likely ip_sum at this point is wrong.
*/
- IPSEC_INIT_CTX(&ctx, &m, sav, AF_INET, IPSEC_ENC_BEFORE);
+ IPSEC_INIT_CTX(&ctx, &m, inp, sav, AF_INET, IPSEC_ENC_BEFORE);
if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0)
goto bad;
@@ -235,9 +236,10 @@ ipsec4_perform_request(struct mbuf *m, struct secpolicy *sp, u_int idx)
/* XXXAE: IPSEC_OSTAT_INC(tunnel); */
goto bad;
}
+ inp = NULL;
}
- IPSEC_INIT_CTX(&ctx, &m, sav, dst->sa.sa_family, IPSEC_ENC_AFTER);
+ IPSEC_INIT_CTX(&ctx, &m, inp, sav, dst->sa.sa_family, IPSEC_ENC_AFTER);
if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0)
goto bad;
@@ -285,7 +287,7 @@ ipsec4_process_packet(struct mbuf *m, struct secpolicy *sp,
struct inpcb *inp)
{
- return (ipsec4_perform_request(m, sp, 0));
+ return (ipsec4_perform_request(m, sp, inp, 0));
}
static int
@@ -491,7 +493,8 @@ next:
* IPsec output logic for IPv6.
*/
static int
-ipsec6_perform_request(struct mbuf *m, struct secpolicy *sp, u_int idx)
+ipsec6_perform_request(struct mbuf *m, struct secpolicy *sp,
+ struct inpcb *inp, u_int idx)
{
struct ipsec_ctx_data ctx;
union sockaddr_union *dst;
@@ -514,7 +517,7 @@ ipsec6_perform_request(struct mbuf *m, struct secpolicy *sp, u_int idx)
ip6 = mtod(m, struct ip6_hdr *);
ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6));
- IPSEC_INIT_CTX(&ctx, &m, sav, AF_INET6, IPSEC_ENC_BEFORE);
+ IPSEC_INIT_CTX(&ctx, &m, inp, sav, AF_INET6, IPSEC_ENC_BEFORE);
if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0)
goto bad;
@@ -540,9 +543,10 @@ ipsec6_perform_request(struct mbuf *m, struct secpolicy *sp, u_int idx)
/* XXXAE: IPSEC_OSTAT_INC(tunnel); */
goto bad;
}
+ inp = NULL;
}
- IPSEC_INIT_CTX(&ctx, &m, sav, dst->sa.sa_family, IPSEC_ENC_AFTER);
+ IPSEC_INIT_CTX(&ctx, &m, inp, sav, dst->sa.sa_family, IPSEC_ENC_AFTER);
if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0)
goto bad;
@@ -585,7 +589,7 @@ ipsec6_process_packet(struct mbuf *m, struct secpolicy *sp,
struct inpcb *inp)
{
- return (ipsec6_perform_request(m, sp, 0));
+ return (ipsec6_perform_request(m, sp, inp, 0));
}
static int
@@ -750,14 +754,14 @@ ipsec_process_done(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
case AF_INET:
key_freesav(&sav);
IPSECSTAT_INC(ips_out_bundlesa);
- return (ipsec4_perform_request(m, sp, idx));
+ return (ipsec4_perform_request(m, sp, NULL, idx));
/* NOTREACHED */
#endif
#ifdef INET6
case AF_INET6:
key_freesav(&sav);
IPSEC6STAT_INC(ips_out_bundlesa);
- return (ipsec6_perform_request(m, sp, idx));
+ return (ipsec6_perform_request(m, sp, NULL, idx));
/* NOTREACHED */
#endif /* INET6 */
default: