From 0e5609475351394c791e132db4e33c768b1a41fc Mon Sep 17 00:00:00 2001 From: bluhm Date: Thu, 13 Sep 2018 19:53:58 +0000 Subject: [PATCH] Add reference counting for inet pcb, this will be needed when we start locking the socket. An inp can be referenced by the PCB queue and hashes, by a pf mbuf header, or by a pf state key. OK visa@ --- sys/kern/uipc_mbuf.c | 7 +++++-- sys/net/pf.c | 34 +++++++++++++++++++++++++++------- sys/net/pfvar.h | 4 +++- sys/netinet/in_pcb.c | 27 +++++++++++++++++++++++++-- sys/netinet/in_pcb.h | 6 +++++- sys/netinet/raw_ip.c | 4 ++-- sys/netinet/tcp_output.c | 8 ++++++-- sys/netinet/udp_usrreq.c | 4 ++-- sys/netinet6/raw_ip6.c | 4 ++-- sys/netinet6/udp6_output.c | 7 +++++-- 10 files changed, 82 insertions(+), 23 deletions(-) diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index 4349c02e882..a506d8e575a 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_mbuf.c,v 1.258 2018/09/10 16:14:07 bluhm Exp $ */ +/* $OpenBSD: uipc_mbuf.c,v 1.259 2018/09/13 19:53:58 bluhm Exp $ */ /* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */ /* @@ -296,9 +296,9 @@ m_clearhdr(struct mbuf *m) { /* delete all mbuf tags to reset the state */ m_tag_delete_chain(m); - #if NPF > 0 pf_mbuf_unlink_state_key(m); + pf_mbuf_unlink_inpcb(m); #endif /* NPF > 0 */ memset(&m->m_pkthdr, 0, sizeof(m->m_pkthdr)); @@ -430,6 +430,7 @@ m_free(struct mbuf *m) m_tag_delete_chain(m); #if NPF > 0 pf_mbuf_unlink_state_key(m); + pf_mbuf_unlink_inpcb(m); #endif /* NPF > 0 */ } if (m->m_flags & M_EXT) @@ -1350,6 +1351,8 @@ m_dup_pkthdr(struct mbuf *to, struct mbuf *from, int wait) #if NPF > 0 to->m_pkthdr.pf.statekey = NULL; pf_mbuf_link_state_key(to, from->m_pkthdr.pf.statekey); + to->m_pkthdr.pf.inp = NULL; + pf_mbuf_link_inpcb(to, from->m_pkthdr.pf.inp); #endif /* NPF > 0 */ SLIST_INIT(&to->m_pkthdr.ph_tags); diff --git a/sys/net/pf.c b/sys/net/pf.c index 03f12f4be6b..76a351278f0 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.1074 2018/09/11 07:53:38 sashan Exp $ */ +/* $OpenBSD: pf.c,v 1.1075 2018/09/13 19:53:58 bluhm Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -4805,7 +4805,7 @@ pf_test_state(struct pf_pdesc *pd, struct pf_state **state, u_short *reason, /* XXX make sure it's the same direction ?? */ (*state)->timeout = PFTM_PURGE; *state = NULL; - pd->m->m_pkthdr.pf.inp = inp; + pf_mbuf_link_inpcb(pd->m, inp); return (PF_DROP); } else if (dst->state >= TCPS_ESTABLISHED && src->state >= TCPS_ESTABLISHED) { @@ -7286,7 +7286,7 @@ void pf_pkt_addr_changed(struct mbuf *m) { pf_mbuf_unlink_state_key(m); - m->m_pkthdr.pf.inp = NULL; + pf_mbuf_unlink_inpcb(m); } struct inpcb * @@ -7390,6 +7390,13 @@ pf_state_key_isvalid(struct pf_state_key *sk) return ((sk != NULL) && (sk->removed == 0)); } +void +pf_mbuf_link_state_key(struct mbuf *m, struct pf_state_key *sk) +{ + KASSERT(m->m_pkthdr.pf.statekey == NULL); + m->m_pkthdr.pf.statekey = pf_state_key_ref(sk); +} + void pf_mbuf_unlink_state_key(struct mbuf *m) { @@ -7402,17 +7409,28 @@ pf_mbuf_unlink_state_key(struct mbuf *m) } void -pf_mbuf_link_state_key(struct mbuf *m, struct pf_state_key *sk) +pf_mbuf_link_inpcb(struct mbuf *m, struct inpcb *inp) { - KASSERT(m->m_pkthdr.pf.statekey == NULL); - m->m_pkthdr.pf.statekey = pf_state_key_ref(sk); + KASSERT(m->m_pkthdr.pf.inp == NULL); + m->m_pkthdr.pf.inp = in_pcbref(inp); +} + +void +pf_mbuf_unlink_inpcb(struct mbuf *m) +{ + struct inpcb *inp = m->m_pkthdr.pf.inp; + + if (inp != NULL) { + m->m_pkthdr.pf.inp = NULL; + in_pcbunref(inp); + } } void pf_state_key_link_inpcb(struct pf_state_key *sk, struct inpcb *inp) { KASSERT(sk->inp == NULL); - sk->inp = inp; + sk->inp = in_pcbref(inp); KASSERT(inp->inp_pf_sk == NULL); inp->inp_pf_sk = pf_state_key_ref(sk); } @@ -7427,6 +7445,7 @@ pf_inpcb_unlink_state_key(struct inpcb *inp) sk->inp = NULL; inp->inp_pf_sk = NULL; pf_state_key_unref(sk); + in_pcbunref(inp); } } @@ -7440,6 +7459,7 @@ pf_state_key_unlink_inpcb(struct pf_state_key *sk) sk->inp = NULL; inp->inp_pf_sk = NULL; pf_state_key_unref(sk); + in_pcbunref(inp); } } diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index fb43fe0b166..476067e560c 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.485 2018/09/11 07:53:38 sashan Exp $ */ +/* $OpenBSD: pfvar.h,v 1.486 2018/09/13 19:53:58 bluhm Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -1961,6 +1961,8 @@ int pf_postprocess_addr(struct pf_state *); void pf_mbuf_link_state_key(struct mbuf *, struct pf_state_key *); void pf_mbuf_unlink_state_key(struct mbuf *); +void pf_mbuf_link_inpcb(struct mbuf *, struct inpcb *); +void pf_mbuf_unlink_inpcb(struct mbuf *); u_int8_t* pf_find_tcpopt(u_int8_t *, u_int8_t *, size_t, u_int8_t, u_int8_t); diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 614d15fa769..346c93534f9 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.c,v 1.243 2018/09/11 14:34:49 bluhm Exp $ */ +/* $OpenBSD: in_pcb.c,v 1.244 2018/09/13 19:53:58 bluhm Exp $ */ /* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */ /* @@ -227,6 +227,7 @@ in_pcballoc(struct socket *so, struct inpcbtable *table) return (ENOBUFS); inp->inp_table = table; inp->inp_socket = so; + refcnt_init(&inp->inp_refcnt); inp->inp_seclevel[SL_AUTH] = IPSEC_AUTH_LEVEL_DEFAULT; inp->inp_seclevel[SL_ESP_TRANS] = IPSEC_ESP_TRANS_LEVEL_DEFAULT; inp->inp_seclevel[SL_ESP_NETWORK] = IPSEC_ESP_NETWORK_LEVEL_DEFAULT; @@ -577,7 +578,29 @@ in_pcbdetach(struct inpcb *inp) LIST_REMOVE(inp, inp_hash); TAILQ_REMOVE(&inp->inp_table->inpt_queue, inp, inp_queue); inp->inp_table->inpt_count--; - pool_put(&inpcb_pool, inp); + in_pcbunref(inp); +} + +struct inpcb * +in_pcbref(struct inpcb *inp) +{ + if (inp != NULL) + refcnt_take(&inp->inp_refcnt); + return inp; +} + +void +in_pcbunref(struct inpcb *inp) +{ + if (refcnt_rele(&inp->inp_refcnt)) { + KASSERT((LIST_NEXT(inp, inp_hash) == NULL) || + (LIST_NEXT(inp, inp_hash) == _Q_INVALID)); + KASSERT((LIST_NEXT(inp, inp_lhash) == NULL) || + (LIST_NEXT(inp, inp_lhash) == _Q_INVALID)); + KASSERT((TAILQ_NEXT(inp, inp_queue) == NULL) || + (TAILQ_NEXT(inp, inp_queue) == _Q_INVALID)); + pool_put(&inpcb_pool, inp); + } } void diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index fdf1973fb17..a26b8a9e79e 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.h,v 1.110 2018/09/11 14:34:49 bluhm Exp $ */ +/* $OpenBSD: in_pcb.h,v 1.111 2018/09/13 19:53:58 bluhm Exp $ */ /* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $ */ /* @@ -110,6 +110,7 @@ struct inpcb { } inp_ru; #define inp_route inp_ru.ru_route #define inp_route6 inp_ru.ru_route6 + struct refcnt inp_refcnt; /* refcount PCB, delay memory free */ int inp_flags; /* generic IP/datagram flags */ union { /* Header prototype. */ struct ip hu_ip; @@ -260,6 +261,9 @@ int in_pcbaddrisavail(struct inpcb *, struct sockaddr_in *, int, struct proc *); int in_pcbconnect(struct inpcb *, struct mbuf *); void in_pcbdetach(struct inpcb *); +struct inpcb * + in_pcbref(struct inpcb *); +void in_pcbunref(struct inpcb *); void in_pcbdisconnect(struct inpcb *); struct inpcb * in_pcbhashlookup(struct inpcbtable *, struct in_addr, diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 35810fcd416..20c9776e9d5 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -1,4 +1,4 @@ -/* $OpenBSD: raw_ip.c,v 1.111 2018/07/05 21:16:52 bluhm Exp $ */ +/* $OpenBSD: raw_ip.c,v 1.112 2018/09/13 19:53:58 bluhm Exp $ */ /* $NetBSD: raw_ip.c,v 1.25 1996/02/18 18:58:33 christos Exp $ */ /* @@ -287,7 +287,7 @@ rip_output(struct mbuf *m, struct socket *so, struct sockaddr *dstaddr, #if NPF > 0 if (inp->inp_socket->so_state & SS_ISCONNECTED && ip->ip_p != IPPROTO_ICMP) - m->m_pkthdr.pf.inp = inp; + pf_mbuf_link_inpcb(m, inp); #endif error = ip_output(m, inp->inp_options, &inp->inp_route, flags, diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index 7abcf26675e..0584c0c2060 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_output.c,v 1.125 2018/06/11 07:40:26 bluhm Exp $ */ +/* $OpenBSD: tcp_output.c,v 1.126 2018/09/13 19:53:58 bluhm Exp $ */ /* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */ /* @@ -78,7 +78,11 @@ #include #include +#include #include +#if NPF > 0 +#include +#endif #include #include @@ -1014,7 +1018,7 @@ send: m->m_pkthdr.ph_rtableid = tp->t_inpcb->inp_rtableid; #if NPF > 0 - m->m_pkthdr.pf.inp = tp->t_inpcb; + pf_mbuf_link_inpcb(m, tp->t_inpcb); #endif switch (tp->pf) { diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index c4c52f68609..3f944589182 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_usrreq.c,v 1.250 2018/07/05 21:16:52 bluhm Exp $ */ +/* $OpenBSD: udp_usrreq.c,v 1.251 2018/09/13 19:53:58 bluhm Exp $ */ /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ /* @@ -998,7 +998,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct mbuf *addr, #if NPF > 0 if (inp->inp_socket->so_state & SS_ISCONNECTED) - m->m_pkthdr.pf.inp = inp; + pf_mbuf_link_inpcb(m, inp); #endif error = ip_output(m, inp->inp_options, &inp->inp_route, diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 80fbcc1a393..8ae55b2832e 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: raw_ip6.c,v 1.129 2018/07/05 21:16:52 bluhm Exp $ */ +/* $OpenBSD: raw_ip6.c,v 1.130 2018/09/13 19:53:58 bluhm Exp $ */ /* $KAME: raw_ip6.c,v 1.69 2001/03/04 15:55:44 itojun Exp $ */ /* @@ -467,7 +467,7 @@ rip6_output(struct mbuf *m, struct socket *so, struct sockaddr *dstaddr, #if NPF > 0 if (in6p->inp_socket->so_state & SS_ISCONNECTED && so->so_proto->pr_protocol != IPPROTO_ICMPV6) - m->m_pkthdr.pf.inp = in6p; + pf_mbuf_link_inpcb(m, in6p); #endif error = ip6_output(m, optp, &in6p->inp_route6, flags, diff --git a/sys/netinet6/udp6_output.c b/sys/netinet6/udp6_output.c index ecece8ae82d..d5df2132084 100644 --- a/sys/netinet6/udp6_output.c +++ b/sys/netinet6/udp6_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp6_output.c,v 1.55 2017/08/11 19:53:02 bluhm Exp $ */ +/* $OpenBSD: udp6_output.c,v 1.56 2018/09/13 19:53:58 bluhm Exp $ */ /* $KAME: udp6_output.c,v 1.21 2001/02/07 11:51:54 itojun Exp $ */ /* @@ -74,6 +74,9 @@ #include #include #include +#if NPF > 0 +#include +#endif #include #include @@ -227,7 +230,7 @@ udp6_output(struct inpcb *in6p, struct mbuf *m, struct mbuf *addr6, #if NPF > 0 if (in6p->inp_socket->so_state & SS_ISCONNECTED) - m->m_pkthdr.pf.inp = in6p; + pf_mbuf_link_inpcb(m, in6p); #endif error = ip6_output(m, optp, &in6p->inp_route6, -- 2.20.1