summaryrefslogtreecommitdiffstats
path: root/sys/netinet
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
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')
-rw-r--r--sys/netinet/ip_fastfwd.c4
-rw-r--r--sys/netinet/ip_fw.h5
-rw-r--r--sys/netinet/ip_fw2.c43
-rw-r--r--sys/netinet/ip_fw_pfil.c8
-rw-r--r--sys/netinet/ip_input.c2
-rw-r--r--sys/netinet/ip_output.c2
6 files changed, 45 insertions, 19 deletions
diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c
index 8d78c0e..9095756 100644
--- a/sys/netinet/ip_fastfwd.c
+++ b/sys/netinet/ip_fastfwd.c
@@ -359,7 +359,7 @@ ip_fastforward(struct mbuf *m)
if (inet_pfil_hook.ph_busy_count == -1)
goto passin;
- if (pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN) ||
+ if (pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN, NULL) ||
m == NULL)
return 1;
@@ -437,7 +437,7 @@ passin:
if (inet_pfil_hook.ph_busy_count == -1)
goto passout;
- if (pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT) || m == NULL) {
+ if (pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT, NULL) || m == NULL) {
goto consumed;
}
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index 0229a22..ac903f5 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -425,6 +425,7 @@ struct ip_fw_args {
struct ipfw_flow_id f_id; /* grabbed from IP header */
u_int32_t retval;
+ struct inpcb *inp;
};
/*
@@ -435,8 +436,8 @@ struct ip_fw_args {
struct sockopt;
struct dn_flow_set;
-int ipfw_check_in(void *, struct mbuf **, struct ifnet *, int);
-int ipfw_check_out(void *, struct mbuf **, struct ifnet *, int);
+int ipfw_check_in(void *, struct mbuf **, struct ifnet *, int, struct inpcb *inp);
+int ipfw_check_out(void *, struct mbuf **, struct ifnet *, int, struct inpcb *inp);
int ipfw_chk(struct ip_fw_args *);
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:
diff --git a/sys/netinet/ip_fw_pfil.c b/sys/netinet/ip_fw_pfil.c
index 69e0188..3b08f69 100644
--- a/sys/netinet/ip_fw_pfil.c
+++ b/sys/netinet/ip_fw_pfil.c
@@ -73,7 +73,8 @@ ip_dn_ruledel_t *ip_dn_ruledel_ptr = NULL;
static int ipfw_divert(struct mbuf **, int, int);
int
-ipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
+ipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
{
struct ip_fw_args args;
struct m_tag *dn_tag;
@@ -102,6 +103,7 @@ ipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
again:
args.m = *m0;
+ args.inp = inp;
ipfw = ipfw_chk(&args);
*m0 = args.m;
@@ -156,7 +158,8 @@ pass:
}
int
-ipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
+ipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
{
struct ip_fw_args args;
struct m_tag *dn_tag;
@@ -186,6 +189,7 @@ ipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
again:
args.m = *m0;
args.oif = ifp;
+ args.inp = inp;
ipfw = ipfw_chk(&args);
*m0 = args.m;
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 223866f..37fbfd6 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -437,7 +437,7 @@ tooshort:
odst = ip->ip_dst;
if (pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif,
- PFIL_IN) != 0)
+ PFIL_IN, NULL) != 0)
return;
if (m == NULL) /* consumed by filter */
return;
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index d50beef..dfc939b 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -662,7 +662,7 @@ spd_done:
/* Run through list of hooks for output packets. */
odst.s_addr = ip->ip_dst.s_addr;
- error = pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT);
+ error = pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT, inp);
if (error != 0 || m == NULL)
goto done;
OpenPOWER on IntegriCloud