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:
bz 2008-10-04 15:06:34 +00:00
parent 848f285a65
commit 77f80e0672
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__
if (inp_arg != NULL) {
INP_LOCK_ASSERT(inp_arg);
if (inp_arg->inp_socket) {
pd->lookup.uid = inp_arg->inp_socket->so_cred->cr_uid;
pd->lookup.gid =
inp_arg->inp_socket->so_cred->cr_groups[0];
return (1);
} else
return (-1);
pd->lookup.uid = inp_arg->inp_cred->cr_uid;
pd->lookup.gid = inp_arg->inp_cred->cr_groups[0];
return (1);
}
#endif
switch (pd->proto) {
@ -3043,15 +3039,9 @@ pf_socket_lookup(int direction, struct pf_pdesc *pd)
return (-1);
}
#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);
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
pd->lookup.uid = inp->inp_socket->so_euid;
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);
inp->inp_pcbinfo = pcbinfo;
inp->inp_socket = so;
inp->inp_cred = crhold(so->so_cred);
inp->inp_inc.inc_fibnum = so->so_fibnum;
#ifdef MAC
error = mac_inpcb_init(inp, M_NOWAIT);
@ -235,8 +236,10 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo)
#if defined(IPSEC) || defined(MAC)
out:
if (error != 0)
if (error != 0) {
crfree(inp->inp_cred);
uma_zfree(pcbinfo->ipi_zone, inp);
}
#endif
return (error);
}
@ -357,7 +360,7 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
if (jailed(cred))
prison = 1;
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) {
t = in_pcblookup_local(pcbinfo, sin->sin_addr,
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 ||
(t->inp_socket->so_options &
SO_REUSEPORT) == 0) &&
(so->so_cred->cr_uid !=
t->inp_socket->so_cred->cr_uid))
(inp->inp_cred->cr_uid !=
t->inp_cred->cr_uid))
return (EADDRINUSE);
}
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)
inp_freemoptions(inp->inp_moptions);
inp->inp_vflag = 0;
crfree(inp->inp_cred);
#ifdef MAC
mac_inpcb_destroy(inp);

View File

@ -153,6 +153,7 @@ struct inpcb {
void *inp_ppcb; /* (i) pointer to per-protocol pcb */
struct inpcbinfo *inp_pcbinfo; /* (c) PCB list info */
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 */
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;
if (inp->inp_socket != NULL) {
cr = inp->inp_socket->so_cred;
ugp->fw_prid = jailed(cr) ?
cr->cr_prison->pr_id : -1;
ugp->fw_uid = cr->cr_uid;
ugp->fw_ngroups = cr->cr_ngroups;
bcopy(cr->cr_groups, ugp->fw_groups,
sizeof(ugp->fw_groups));
}
cr = inp->inp_cred;
ugp->fw_prid = jailed(cr) ? cr->cr_prison->pr_id : -1;
ugp->fw_uid = cr->cr_uid;
ugp->fw_ngroups = cr->cr_ngroups;
bcopy(cr->cr_groups, ugp->fw_groups, sizeof(ugp->fw_groups));
}
static int
@ -2042,12 +2038,8 @@ check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif,
dst_ip, htons(dst_port),
wildcard, NULL);
if (pcb != NULL) {
INP_RLOCK(pcb);
if (pcb->inp_socket != NULL) {
fill_ugid_cache(pcb, ugp);
*ugid_lookupp = 1;
}
INP_RUNLOCK(pcb);
fill_ugid_cache(pcb, ugp);
*ugid_lookupp = 1;
}
INP_INFO_RUNLOCK(pi);
if (*ugid_lookupp == 0) {

View File

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

View File

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

View File

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

View File

@ -189,7 +189,7 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
0))
return (EACCES);
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) {
t = in6_pcblookup_local(pcbinfo,
&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(&t->in6p_laddr) ||
(t->inp_socket->so_options & SO_REUSEPORT)
== 0) && (so->so_cred->cr_uid !=
t->inp_socket->so_cred->cr_uid))
== 0) && (inp->inp_cred->cr_uid !=
t->inp_cred->cr_uid))
return (EADDRINUSE);
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
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 ||
ntohl(t->inp_faddr.s_addr) ==
INADDR_ANY) &&
(so->so_cred->cr_uid !=
t->inp_socket->so_cred->cr_uid))
(inp->inp_cred->cr_uid !=
t->inp_cred->cr_uid))
return (EADDRINUSE);
}
}
@ -323,7 +323,7 @@ in6_pcbladdr(register struct inpcb *inp, struct sockaddr *nam,
*/
*plocal_addr6 = in6_selectsrc(sin6, inp->in6p_outputopts,
inp, NULL,
inp->inp_socket->so_cred,
inp->inp_cred,
&ifp, &error);
if (ifp && scope_ambiguous &&
(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,
inp->inp_socket);
if (error == 0)
cru2x(inp->inp_socket->so_cred, &xuc);
cru2x(inp->inp_cred, &xuc);
INP_RUNLOCK(inp);
} else {
INP_INFO_RUNLOCK(&V_udbinfo);