From owner-svn-src-head@freebsd.org Mon Jul 31 11:04:37 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 008E3DD0368; Mon, 31 Jul 2017 11:04:37 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id D06BE72A4F; Mon, 31 Jul 2017 11:04:36 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v6VB4aFe089405; Mon, 31 Jul 2017 11:04:36 GMT (envelope-from ae@FreeBSD.org) Received: (from ae@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v6VB4ZeM089400; Mon, 31 Jul 2017 11:04:35 GMT (envelope-from ae@FreeBSD.org) Message-Id: <201707311104.v6VB4ZeM089400@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ae set sender to ae@FreeBSD.org using -f From: "Andrey V. Elsukov" Date: Mon, 31 Jul 2017 11:04:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r321779 - in head/sys: net netipsec X-SVN-Group: head X-SVN-Commit-Author: ae X-SVN-Commit-Paths: in head/sys: net netipsec X-SVN-Commit-Revision: 321779 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 31 Jul 2017 11:04:37 -0000 Author: ae Date: Mon Jul 31 11:04:35 2017 New Revision: 321779 URL: https://svnweb.freebsd.org/changeset/base/321779 Log: 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 Modified: head/sys/net/if_enc.c head/sys/net/if_enc.h head/sys/netipsec/ipsec.h head/sys/netipsec/ipsec_input.c head/sys/netipsec/ipsec_output.c Modified: head/sys/net/if_enc.c ============================================================================== --- head/sys/net/if_enc.c Mon Jul 31 09:54:04 2017 (r321778) +++ head/sys/net/if_enc.c Mon Jul 31 11:04:35 2017 (r321779) @@ -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: head/sys/net/if_enc.h ============================================================================== --- head/sys/net/if_enc.h Mon Jul 31 09:54:04 2017 (r321778) +++ head/sys/net/if_enc.h Mon Jul 31 11:04:35 2017 (r321779) @@ -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: head/sys/netipsec/ipsec.h ============================================================================== --- head/sys/netipsec/ipsec.h Mon Jul 31 09:54:04 2017 (r321778) +++ head/sys/netipsec/ipsec.h Mon Jul 31 11:04:35 2017 (r321779) @@ -253,8 +253,9 @@ struct ipsecstat { #include 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: head/sys/netipsec/ipsec_input.c ============================================================================== --- head/sys/netipsec/ipsec_input.c Mon Jul 31 09:54:04 2017 (r321778) +++ head/sys/netipsec/ipsec_input.c Mon Jul 31 11:04:35 2017 (r321779) @@ -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: head/sys/netipsec/ipsec_output.c ============================================================================== --- head/sys/netipsec/ipsec_output.c Mon Jul 31 09:54:04 2017 (r321778) +++ head/sys/netipsec/ipsec_output.c Mon Jul 31 11:04:35 2017 (r321779) @@ -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: