Cache so_cred as inp_cred in the inpcb.

This means that inp_cred is always there, even after the socket
has gone away. It also means that it is constant for the lifetime
of the inp.
Both facts lead to simpler code and possibly less locking.

Suggested by:	rwatson
Reviewed by:	rwatson
MFC after:	6 weeks
X-MFC Note:	use a inp_pspare for inp_cred
This commit is contained in:
Bjoern A. Zeeb 2008-10-04 15:06:34 +00:00
parent 6059e92408
commit 86d02c5c63
9 changed files with 43 additions and 55 deletions

View File

@ -2941,13 +2941,9 @@ pf_socket_lookup(int direction, struct pf_pdesc *pd)
#ifdef __FreeBSD__ #ifdef __FreeBSD__
if (inp_arg != NULL) { if (inp_arg != NULL) {
INP_LOCK_ASSERT(inp_arg); INP_LOCK_ASSERT(inp_arg);
if (inp_arg->inp_socket) { pd->lookup.uid = inp_arg->inp_cred->cr_uid;
pd->lookup.uid = inp_arg->inp_socket->so_cred->cr_uid; pd->lookup.gid = inp_arg->inp_cred->cr_groups[0];
pd->lookup.gid = return (1);
inp_arg->inp_socket->so_cred->cr_groups[0];
return (1);
} else
return (-1);
} }
#endif #endif
switch (pd->proto) { switch (pd->proto) {
@ -3043,15 +3039,9 @@ pf_socket_lookup(int direction, struct pf_pdesc *pd)
return (-1); return (-1);
} }
#ifdef __FreeBSD__ #ifdef __FreeBSD__
INP_RLOCK(inp); pd->lookup.uid = inp->inp_cred->cr_uid;
pd->lookup.gid = inp->inp_cred->cr_groups[0];
INP_INFO_RUNLOCK(pi); INP_INFO_RUNLOCK(pi);
if ((inp->inp_socket == NULL) || (inp->inp_socket->so_cred == NULL)) {
INP_RUNLOCK(inp);
return (-1);
}
pd->lookup.uid = inp->inp_socket->so_cred->cr_uid;
pd->lookup.gid = inp->inp_socket->so_cred->cr_groups[0];
INP_RUNLOCK(inp);
#else #else
pd->lookup.uid = inp->inp_socket->so_euid; pd->lookup.uid = inp->inp_socket->so_euid;
pd->lookup.gid = inp->inp_socket->so_egid; pd->lookup.gid = inp->inp_socket->so_egid;

View File

@ -197,6 +197,7 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo)
bzero(inp, inp_zero_size); bzero(inp, inp_zero_size);
inp->inp_pcbinfo = pcbinfo; inp->inp_pcbinfo = pcbinfo;
inp->inp_socket = so; inp->inp_socket = so;
inp->inp_cred = crhold(so->so_cred);
inp->inp_inc.inc_fibnum = so->so_fibnum; inp->inp_inc.inc_fibnum = so->so_fibnum;
#ifdef MAC #ifdef MAC
error = mac_inpcb_init(inp, M_NOWAIT); error = mac_inpcb_init(inp, M_NOWAIT);
@ -235,8 +236,10 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo)
#if defined(IPSEC) || defined(MAC) #if defined(IPSEC) || defined(MAC)
out: out:
if (error != 0) if (error != 0) {
crfree(inp->inp_cred);
uma_zfree(pcbinfo->ipi_zone, inp); uma_zfree(pcbinfo->ipi_zone, inp);
}
#endif #endif
return (error); return (error);
} }
@ -357,7 +360,7 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
if (jailed(cred)) if (jailed(cred))
prison = 1; prison = 1;
if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) && if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) &&
priv_check_cred(so->so_cred, priv_check_cred(inp->inp_cred,
PRIV_NETINET_REUSEPORT, 0) != 0) { PRIV_NETINET_REUSEPORT, 0) != 0) {
t = in_pcblookup_local(pcbinfo, sin->sin_addr, t = in_pcblookup_local(pcbinfo, sin->sin_addr,
lport, prison ? 0 : INPLOOKUP_WILDCARD, lport, prison ? 0 : INPLOOKUP_WILDCARD,
@ -374,8 +377,8 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
ntohl(t->inp_laddr.s_addr) != INADDR_ANY || ntohl(t->inp_laddr.s_addr) != INADDR_ANY ||
(t->inp_socket->so_options & (t->inp_socket->so_options &
SO_REUSEPORT) == 0) && SO_REUSEPORT) == 0) &&
(so->so_cred->cr_uid != (inp->inp_cred->cr_uid !=
t->inp_socket->so_cred->cr_uid)) t->inp_cred->cr_uid))
return (EADDRINUSE); return (EADDRINUSE);
} }
if (prison && prison_ip(cred, 0, &sin->sin_addr.s_addr)) if (prison && prison_ip(cred, 0, &sin->sin_addr.s_addr))
@ -901,6 +904,7 @@ in_pcbfree(struct inpcb *inp)
if (inp->inp_moptions != NULL) if (inp->inp_moptions != NULL)
inp_freemoptions(inp->inp_moptions); inp_freemoptions(inp->inp_moptions);
inp->inp_vflag = 0; inp->inp_vflag = 0;
crfree(inp->inp_cred);
#ifdef MAC #ifdef MAC
mac_inpcb_destroy(inp); mac_inpcb_destroy(inp);

View File

@ -153,6 +153,7 @@ struct inpcb {
void *inp_ppcb; /* (i) pointer to per-protocol pcb */ void *inp_ppcb; /* (i) pointer to per-protocol pcb */
struct inpcbinfo *inp_pcbinfo; /* (c) PCB list info */ struct inpcbinfo *inp_pcbinfo; /* (c) PCB list info */
struct socket *inp_socket; /* (i) back pointer to socket */ struct socket *inp_socket; /* (i) back pointer to socket */
struct ucred *inp_cred; /* (c) cache of socket cred */
u_int32_t inp_flow; /* (i) IPv6 flow information */ u_int32_t inp_flow; /* (i) IPv6 flow information */
int inp_flags; /* (i) generic IP/datagram flags */ int inp_flags; /* (i) generic IP/datagram flags */

View File

@ -1977,15 +1977,11 @@ fill_ugid_cache(struct inpcb *inp, struct ip_fw_ugid *ugp)
{ {
struct ucred *cr; struct ucred *cr;
if (inp->inp_socket != NULL) { cr = inp->inp_cred;
cr = inp->inp_socket->so_cred; ugp->fw_prid = jailed(cr) ? cr->cr_prison->pr_id : -1;
ugp->fw_prid = jailed(cr) ? ugp->fw_uid = cr->cr_uid;
cr->cr_prison->pr_id : -1; ugp->fw_ngroups = cr->cr_ngroups;
ugp->fw_uid = cr->cr_uid; bcopy(cr->cr_groups, ugp->fw_groups, sizeof(ugp->fw_groups));
ugp->fw_ngroups = cr->cr_ngroups;
bcopy(cr->cr_groups, ugp->fw_groups,
sizeof(ugp->fw_groups));
}
} }
static int static int
@ -2042,12 +2038,8 @@ check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif,
dst_ip, htons(dst_port), dst_ip, htons(dst_port),
wildcard, NULL); wildcard, NULL);
if (pcb != NULL) { if (pcb != NULL) {
INP_RLOCK(pcb); fill_ugid_cache(pcb, ugp);
if (pcb->inp_socket != NULL) { *ugid_lookupp = 1;
fill_ugid_cache(pcb, ugp);
*ugid_lookupp = 1;
}
INP_RUNLOCK(pcb);
} }
INP_INFO_RUNLOCK(pi); INP_INFO_RUNLOCK(pi);
if (*ugid_lookupp == 0) { if (*ugid_lookupp == 0) {

View File

@ -261,6 +261,7 @@ rip_input(struct mbuf *m, int off)
if (inp->inp_ip_p != proto) if (inp->inp_ip_p != proto)
continue; continue;
#ifdef INET6 #ifdef INET6
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV4) == 0) if ((inp->inp_vflag & INP_IPV4) == 0)
continue; continue;
#endif #endif
@ -268,11 +269,9 @@ rip_input(struct mbuf *m, int off)
continue; continue;
if (inp->inp_faddr.s_addr != ip->ip_src.s_addr) if (inp->inp_faddr.s_addr != ip->ip_src.s_addr)
continue; continue;
INP_RLOCK(inp); if (jailed(inp->inp_cred) &&
if (jailed(inp->inp_socket->so_cred) && (htonl(prison_getip(inp->inp_cred)) !=
(htonl(prison_getip(inp->inp_socket->so_cred)) !=
ip->ip_dst.s_addr)) { ip->ip_dst.s_addr)) {
INP_RUNLOCK(inp);
continue; continue;
} }
if (last) { if (last) {
@ -284,12 +283,14 @@ rip_input(struct mbuf *m, int off)
/* XXX count dropped packet */ /* XXX count dropped packet */
INP_RUNLOCK(last); INP_RUNLOCK(last);
} }
INP_RLOCK(inp);
last = inp; last = inp;
} }
LIST_FOREACH(inp, &V_ripcbinfo.ipi_hashbase[0], inp_hash) { LIST_FOREACH(inp, &V_ripcbinfo.ipi_hashbase[0], inp_hash) {
if (inp->inp_ip_p && inp->inp_ip_p != proto) if (inp->inp_ip_p && inp->inp_ip_p != proto)
continue; continue;
#ifdef INET6 #ifdef INET6
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV4) == 0) if ((inp->inp_vflag & INP_IPV4) == 0)
continue; continue;
#endif #endif
@ -299,9 +300,8 @@ rip_input(struct mbuf *m, int off)
if (inp->inp_faddr.s_addr && if (inp->inp_faddr.s_addr &&
inp->inp_faddr.s_addr != ip->ip_src.s_addr) inp->inp_faddr.s_addr != ip->ip_src.s_addr)
continue; continue;
INP_RLOCK(inp); if (jailed(inp->inp_cred) &&
if (jailed(inp->inp_socket->so_cred) && (htonl(prison_getip(inp->inp_cred)) !=
(htonl(prison_getip(inp->inp_socket->so_cred)) !=
ip->ip_dst.s_addr)) { ip->ip_dst.s_addr)) {
INP_RUNLOCK(inp); INP_RUNLOCK(inp);
continue; continue;
@ -315,6 +315,7 @@ rip_input(struct mbuf *m, int off)
/* XXX count dropped packet */ /* XXX count dropped packet */
INP_RUNLOCK(last); INP_RUNLOCK(last);
} }
INP_RLOCK(inp);
last = inp; last = inp;
} }
INP_INFO_RUNLOCK(&V_ripcbinfo); INP_INFO_RUNLOCK(&V_ripcbinfo);
@ -365,9 +366,9 @@ rip_output(struct mbuf *m, struct socket *so, u_long dst)
ip->ip_off = 0; ip->ip_off = 0;
ip->ip_p = inp->inp_ip_p; ip->ip_p = inp->inp_ip_p;
ip->ip_len = m->m_pkthdr.len; ip->ip_len = m->m_pkthdr.len;
if (jailed(inp->inp_socket->so_cred)) if (jailed(inp->inp_cred))
ip->ip_src.s_addr = ip->ip_src.s_addr =
htonl(prison_getip(inp->inp_socket->so_cred)); htonl(prison_getip(inp->inp_cred));
else else
ip->ip_src = inp->inp_laddr; ip->ip_src = inp->inp_laddr;
ip->ip_dst.s_addr = dst; ip->ip_dst.s_addr = dst;
@ -379,9 +380,9 @@ rip_output(struct mbuf *m, struct socket *so, u_long dst)
} }
INP_RLOCK(inp); INP_RLOCK(inp);
ip = mtod(m, struct ip *); ip = mtod(m, struct ip *);
if (jailed(inp->inp_socket->so_cred)) { if (jailed(inp->inp_cred)) {
if (ip->ip_src.s_addr != if (ip->ip_src.s_addr !=
htonl(prison_getip(inp->inp_socket->so_cred))) { htonl(prison_getip(inp->inp_cred))) {
INP_RUNLOCK(inp); INP_RUNLOCK(inp);
m_freem(m); m_freem(m);
return (EPERM); return (EPERM);

View File

@ -1107,7 +1107,7 @@ tcp_getcred(SYSCTL_HANDLER_ARGS)
error = cr_canseesocket(req->td->td_ucred, error = cr_canseesocket(req->td->td_ucred,
inp->inp_socket); inp->inp_socket);
if (error == 0) if (error == 0)
cru2x(inp->inp_socket->so_cred, &xuc); cru2x(inp->inp_cred, &xuc);
INP_RUNLOCK(inp); INP_RUNLOCK(inp);
} else { } else {
INP_INFO_RUNLOCK(&V_tcbinfo); INP_INFO_RUNLOCK(&V_tcbinfo);
@ -1171,7 +1171,7 @@ tcp6_getcred(SYSCTL_HANDLER_ARGS)
error = cr_canseesocket(req->td->td_ucred, error = cr_canseesocket(req->td->td_ucred,
inp->inp_socket); inp->inp_socket);
if (error == 0) if (error == 0)
cru2x(inp->inp_socket->so_cred, &xuc); cru2x(inp->inp_cred, &xuc);
INP_RUNLOCK(inp); INP_RUNLOCK(inp);
} else { } else {
INP_INFO_RUNLOCK(&V_tcbinfo); INP_INFO_RUNLOCK(&V_tcbinfo);

View File

@ -761,7 +761,7 @@ udp_getcred(SYSCTL_HANDLER_ARGS)
error = cr_canseesocket(req->td->td_ucred, error = cr_canseesocket(req->td->td_ucred,
inp->inp_socket); inp->inp_socket);
if (error == 0) if (error == 0)
cru2x(inp->inp_socket->so_cred, &xuc); cru2x(inp->inp_cred, &xuc);
INP_RUNLOCK(inp); INP_RUNLOCK(inp);
} else { } else {
INP_INFO_RUNLOCK(&V_udbinfo); INP_INFO_RUNLOCK(&V_udbinfo);

View File

@ -189,7 +189,7 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
0)) 0))
return (EACCES); return (EACCES);
if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) && if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) &&
priv_check_cred(so->so_cred, priv_check_cred(inp->inp_cred,
PRIV_NETINET_REUSEPORT, 0) != 0) { PRIV_NETINET_REUSEPORT, 0) != 0) {
t = in6_pcblookup_local(pcbinfo, t = in6_pcblookup_local(pcbinfo,
&sin6->sin6_addr, lport, &sin6->sin6_addr, lport,
@ -201,8 +201,8 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
(!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
!IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) || !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
(t->inp_socket->so_options & SO_REUSEPORT) (t->inp_socket->so_options & SO_REUSEPORT)
== 0) && (so->so_cred->cr_uid != == 0) && (inp->inp_cred->cr_uid !=
t->inp_socket->so_cred->cr_uid)) t->inp_cred->cr_uid))
return (EADDRINUSE); return (EADDRINUSE);
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 && if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
@ -218,8 +218,8 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
(so->so_type != SOCK_STREAM || (so->so_type != SOCK_STREAM ||
ntohl(t->inp_faddr.s_addr) == ntohl(t->inp_faddr.s_addr) ==
INADDR_ANY) && INADDR_ANY) &&
(so->so_cred->cr_uid != (inp->inp_cred->cr_uid !=
t->inp_socket->so_cred->cr_uid)) t->inp_cred->cr_uid))
return (EADDRINUSE); return (EADDRINUSE);
} }
} }
@ -323,7 +323,7 @@ in6_pcbladdr(register struct inpcb *inp, struct sockaddr *nam,
*/ */
*plocal_addr6 = in6_selectsrc(sin6, inp->in6p_outputopts, *plocal_addr6 = in6_selectsrc(sin6, inp->in6p_outputopts,
inp, NULL, inp, NULL,
inp->inp_socket->so_cred, inp->inp_cred,
&ifp, &error); &ifp, &error);
if (ifp && scope_ambiguous && if (ifp && scope_ambiguous &&
(error = in6_setscope(&sin6->sin6_addr, ifp, NULL)) != 0) { (error = in6_setscope(&sin6->sin6_addr, ifp, NULL)) != 0) {

View File

@ -466,7 +466,7 @@ udp6_getcred(SYSCTL_HANDLER_ARGS)
error = cr_canseesocket(req->td->td_ucred, error = cr_canseesocket(req->td->td_ucred,
inp->inp_socket); inp->inp_socket);
if (error == 0) if (error == 0)
cru2x(inp->inp_socket->so_cred, &xuc); cru2x(inp->inp_cred, &xuc);
INP_RUNLOCK(inp); INP_RUNLOCK(inp);
} else { } else {
INP_INFO_RUNLOCK(&V_udbinfo); INP_INFO_RUNLOCK(&V_udbinfo);