Teach pf and ipfw to use read locks in inpcbs write than write locks

when reading credential data from sockets.

Teach pf to unlock the pcbinfo more quickly once it has acquired an
inpcb lock, as the inpcb lock is sufficient to protect the reference.

Assert locks, rather than read locks or write locks, on inpcbs in
subroutines--this is necessary as the inpcb may be passed down with a
write lock from the protocol, or may be passed down with a read lock
from the firewall lookup routine, and either is sufficient.

MFC after:	3 months
This commit is contained in:
Robert Watson 2008-04-20 00:21:54 +00:00
parent 42018dcf7b
commit fdd9b0723e
2 changed files with 8 additions and 9 deletions

View File

@ -2915,7 +2915,7 @@ pf_socket_lookup(int direction, struct pf_pdesc *pd)
pd->lookup.pid = NO_PID; /* XXX: revisit */
#ifdef __FreeBSD__
if (inp_arg != NULL) {
INP_WLOCK_ASSERT(inp_arg);
INP_LOCK_ASSERT(inp_arg);
if (inp_arg->inp_socket) {
pd->lookup.uid = inp_arg->inp_socket->so_cred->cr_uid;
pd->lookup.gid =
@ -3018,16 +3018,15 @@ pf_socket_lookup(int direction, struct pf_pdesc *pd)
return (-1);
}
#ifdef __FreeBSD__
INP_WLOCK(inp);
INP_RLOCK(inp);
INP_INFO_RUNLOCK(pi);
if ((inp->inp_socket == NULL) || (inp->inp_socket->so_cred == NULL)) {
INP_WUNLOCK(inp);
INP_INFO_RUNLOCK(pi);
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_WUNLOCK(inp);
INP_INFO_RUNLOCK(pi);
INP_RUNLOCK(inp);
#else
pd->lookup.uid = inp->inp_socket->so_euid;
pd->lookup.gid = inp->inp_socket->so_egid;

View File

@ -1974,7 +1974,7 @@ check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif,
* up the PCB, we can use the one that was supplied.
*/
if (inp && *lookup == 0) {
INP_WLOCK_ASSERT(inp);
INP_LOCK_ASSERT(inp);
if (inp->inp_socket != NULL) {
fill_ugid_cache(inp, ugp);
*lookup = 1;
@ -2008,12 +2008,12 @@ check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif,
dst_ip, htons(dst_port),
wildcard, NULL);
if (pcb != NULL) {
INP_WLOCK(pcb);
INP_RLOCK(pcb);
if (pcb->inp_socket != NULL) {
fill_ugid_cache(pcb, ugp);
*lookup = 1;
}
INP_WUNLOCK(pcb);
INP_RUNLOCK(pcb);
}
INP_INFO_RUNLOCK(pi);
if (*lookup == 0) {