svn commit: r322741 - in stable/11/sys: net netipsec

Andrey V. Elsukov ae at FreeBSD.org
Mon Aug 21 09:03:22 UTC 2017


Author: ae
Date: Mon Aug 21 09:03:20 2017
New Revision: 322741
URL: https://svnweb.freebsd.org/changeset/base/322741

Log:
  MFC r321779:
    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
    Sponsored by:	Yandex LLC

Modified:
  stable/11/sys/net/if_enc.c
  stable/11/sys/net/if_enc.h
  stable/11/sys/netipsec/ipsec.h
  stable/11/sys/netipsec/ipsec_input.c
  stable/11/sys/netipsec/ipsec_output.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/net/if_enc.c
==============================================================================
--- stable/11/sys/net/if_enc.c	Mon Aug 21 07:03:02 2017	(r322740)
+++ stable/11/sys/net/if_enc.c	Mon Aug 21 09:03:20 2017	(r322741)
@@ -284,7 +284,7 @@ enc_hhook(int32_t hhook_type, int32_t hhook_id, void *
 	/* 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);

Modified: stable/11/sys/net/if_enc.h
==============================================================================
--- stable/11/sys/net/if_enc.h	Mon Aug 21 07:03:02 2017	(r322740)
+++ stable/11/sys/net/if_enc.h	Mon Aug 21 09:03:20 2017	(r322741)
@@ -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

Modified: stable/11/sys/netipsec/ipsec.h
==============================================================================
--- stable/11/sys/netipsec/ipsec.h	Mon Aug 21 07:03:02 2017	(r322740)
+++ stable/11/sys/netipsec/ipsec.h	Mon Aug 21 09:03:20 2017	(r322741)
@@ -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);				\

Modified: stable/11/sys/netipsec/ipsec_input.c
==============================================================================
--- stable/11/sys/netipsec/ipsec_input.c	Mon Aug 21 07:03:02 2017	(r322740)
+++ stable/11/sys/netipsec/ipsec_input.c	Mon Aug 21 09:03:20 2017	(r322741)
@@ -325,7 +325,7 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar
 	    (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
 		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
 		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
 	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) {

Modified: stable/11/sys/netipsec/ipsec_output.c
==============================================================================
--- stable/11/sys/netipsec/ipsec_output.c	Mon Aug 21 07:03:02 2017	(r322740)
+++ stable/11/sys/netipsec/ipsec_output.c	Mon Aug 21 09:03:20 2017	(r322741)
@@ -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 secpolic
 	/*
 	 * 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 secpolic
 			/* 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
     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 secpolic
 	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 secpolic
 			/* 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
     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 *s
 		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:


More information about the svn-src-all mailing list