summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_fw2.c
diff options
context:
space:
mode:
authormlaier <mlaier@FreeBSD.org>2004-09-29 04:54:33 +0000
committermlaier <mlaier@FreeBSD.org>2004-09-29 04:54:33 +0000
commitb65eae4c193f1c3c9580e5ac2bad5585034743f2 (patch)
treeb760834c7691b17430788d5a6041455045da8ac1 /sys/netinet/ip_fw2.c
parente455dd69f84961133d47cca1588021dfafac9e28 (diff)
downloadFreeBSD-src-b65eae4c193f1c3c9580e5ac2bad5585034743f2.zip
FreeBSD-src-b65eae4c193f1c3c9580e5ac2bad5585034743f2.tar.gz
Add an additional struct inpcb * argument to pfil(9) in order to enable
passing along socket information. This is required to work around a LOR with the socket code which results in an easy reproducible hard lockup with debug.mpsafenet=1. This commit does *not* fix the LOR, but enables us to do so later. The missing piece is to turn the filter locking into a leaf lock and will follow in a seperate (later) commit. This will hopefully be MT5'ed in order to fix the problem for RELENG_5 in forseeable future. Suggested by: rwatson A lot of work by: csjp (he'd be even more helpful w/o mentor-reviews ;) Reviewed by: rwatson, csjp Tested by: -pf, -ipfw, LINT, csjp and myself MFC after: 3 days LOR IDs: 14 - 17 (not fixed yet)
Diffstat (limited to 'sys/netinet/ip_fw2.c')
-rw-r--r--sys/netinet/ip_fw2.c43
1 files changed, 32 insertions, 11 deletions
diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c
index a33b361..a8bcede 100644
--- a/sys/netinet/ip_fw2.c
+++ b/sys/netinet/ip_fw2.c
@@ -1532,21 +1532,48 @@ dump_table(ipfw_table *tbl)
return (0);
}
+static void
+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));
+ }
+}
+
static int
check_uidgid(ipfw_insn_u32 *insn,
int proto, struct ifnet *oif,
struct in_addr dst_ip, u_int16_t dst_port,
struct in_addr src_ip, u_int16_t src_port,
- struct ip_fw_ugid *ugp, int *lookup)
+ struct ip_fw_ugid *ugp, int *lookup, struct inpcb *inp)
{
struct inpcbinfo *pi;
int wildcard;
struct inpcb *pcb;
int match;
- struct ucred *cr;
gid_t *gp;
/*
+ * Check to see if the UDP or TCP stack supplied us with
+ * the PCB. If so, rather then holding a lock and looking
+ * up the PCB, we can use the one that was supplied.
+ */
+ if (inp && *lookup == 0) {
+ INP_LOCK_ASSERT(inp);
+ if (inp->inp_socket != NULL) {
+ fill_ugid_cache(inp, ugp);
+ *lookup = 1;
+ }
+ }
+ /*
* If we have already been here and the packet has no
* PCB entry associated with it, then we can safely
* assume that this is a no match.
@@ -1563,7 +1590,7 @@ check_uidgid(ipfw_insn_u32 *insn,
return 0;
match = 0;
if (*lookup == 0) {
- INP_INFO_RLOCK(pi); /* XXX LOR with IPFW */
+ INP_INFO_RLOCK(pi);
pcb = (oif) ?
in_pcblookup_hash(pi,
dst_ip, htons(dst_port),
@@ -1576,13 +1603,7 @@ check_uidgid(ipfw_insn_u32 *insn,
if (pcb != NULL) {
INP_LOCK(pcb);
if (pcb->inp_socket != NULL) {
- cr = pcb->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));
+ fill_ugid_cache(pcb, ugp);
*lookup = 1;
}
INP_UNLOCK(pcb);
@@ -1938,7 +1959,7 @@ check_body:
proto, oif,
dst_ip, dst_port,
src_ip, src_port, &fw_ugid_cache,
- &ugid_lookup);
+ &ugid_lookup, args->inp);
break;
case O_RECV:
OpenPOWER on IntegriCloud