summaryrefslogtreecommitdiffstats
path: root/sys/contrib
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/contrib
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/contrib')
-rw-r--r--sys/contrib/ipfilter/netinet/ip_fil.c27
-rw-r--r--sys/contrib/pf/net/pf.c87
-rw-r--r--sys/contrib/pf/net/pf_ioctl.c28
-rw-r--r--sys/contrib/pf/net/pfvar.h11
4 files changed, 137 insertions, 16 deletions
diff --git a/sys/contrib/ipfilter/netinet/ip_fil.c b/sys/contrib/ipfilter/netinet/ip_fil.c
index 9ac3fb2..954f540 100644
--- a/sys/contrib/ipfilter/netinet/ip_fil.c
+++ b/sys/contrib/ipfilter/netinet/ip_fil.c
@@ -312,7 +312,8 @@ int dir;
}
# endif
#endif /* __NetBSD_Version >= 105110000 && _KERNEL */
-#if (__FreeBSD_version >= 501108) && defined(_KERNEL)
+#if (__FreeBSD_version >= 501108) && (__FreeBSD_version < 600004) && \
+ defined(_KERNEL)
static int
fr_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
@@ -331,7 +332,29 @@ fr_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
ifp, (dir == PFIL_OUT), mp));
}
# endif
-#endif /* __FreeBSD_version >= 501108 */
+
+#elif (__FreeBSD_version >= 600004) && defined(_KERNEL)
+
+static int
+fr_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
+{
+ struct ip *ip = mtod(*mp, struct ip *);
+ return fr_check(ip, ip->ip_hl << 2, ifp, (dir == PFIL_OUT), mp);
+}
+
+# ifdef USE_INET6
+# include <netinet/ip6.h>
+
+static int
+fr_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
+{
+ return (fr_check(mtod(*mp, struct ip *), sizeof(struct ip6_hdr),
+ ifp, (dir == PFIL_OUT), mp));
+}
+# endif
+#endif /* __FreeBSD_version >= 600004 && _KERNEL */
#ifdef _KERNEL
# if defined(IPFILTER_LKM) && !defined(__sgi)
int iplidentify(s)
diff --git a/sys/contrib/pf/net/pf.c b/sys/contrib/pf/net/pf.c
index 9e2bfee..2a5b627 100644
--- a/sys/contrib/pf/net/pf.c
+++ b/sys/contrib/pf/net/pf.c
@@ -185,11 +185,19 @@ struct pf_rule *pf_get_translation(struct pf_pdesc *, struct mbuf *,
int pf_test_tcp(struct pf_rule **, struct pf_state **,
int, struct pfi_kif *, struct mbuf *, int,
void *, struct pf_pdesc *, struct pf_rule **,
+#ifdef __FreeBSD__
+ struct pf_ruleset **, struct inpcb *);
+#else
struct pf_ruleset **);
+#endif
int pf_test_udp(struct pf_rule **, struct pf_state **,
int, struct pfi_kif *, struct mbuf *, int,
void *, struct pf_pdesc *, struct pf_rule **,
+#ifdef __FreeBSD__
+ struct pf_ruleset **, struct inpcb *);
+#else
struct pf_ruleset **);
+#endif
int pf_test_icmp(struct pf_rule **, struct pf_state **,
int, struct pfi_kif *, struct mbuf *, int,
void *, struct pf_pdesc *, struct pf_rule **,
@@ -229,8 +237,13 @@ void pf_route(struct mbuf **, struct pf_rule *, int,
struct ifnet *, struct pf_state *);
void pf_route6(struct mbuf **, struct pf_rule *, int,
struct ifnet *, struct pf_state *);
+#ifdef __FreeBSD__
+int pf_socket_lookup(uid_t *, gid_t *,
+ int, struct pf_pdesc *, struct inpcb *);
+#else
int pf_socket_lookup(uid_t *, gid_t *,
int, struct pf_pdesc *);
+#endif
u_int8_t pf_get_wscale(struct mbuf *, int, u_int16_t,
sa_family_t);
u_int16_t pf_get_mss(struct mbuf *, int, u_int16_t,
@@ -2376,7 +2389,12 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
}
int
+#ifdef __FreeBSD__
+pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, struct pf_pdesc *pd,
+ struct inpcb *inp_arg)
+#else
pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, struct pf_pdesc *pd)
+#endif
{
struct pf_addr *saddr, *daddr;
u_int16_t sport, dport;
@@ -2389,6 +2407,17 @@ pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, struct pf_pdesc *pd)
*uid = UID_MAX;
*gid = GID_MAX;
+#ifdef __FreeBSD__
+ if (inp_arg != NULL) {
+ INP_LOCK_ASSERT(inp_arg);
+ if (inp_arg->inp_socket) {
+ *uid = inp_arg->inp_socket->so_cred->cr_uid;
+ *gid = inp_arg->inp_socket->so_cred->cr_groups[0];
+ return (1);
+ } else
+ return (0);
+ }
+#endif
switch (pd->proto) {
case IPPROTO_TCP:
sport = pd->hdr.tcp->th_sport;
@@ -2663,7 +2692,12 @@ pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr)
int
pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
struct pfi_kif *kif, struct mbuf *m, int off, void *h,
+#ifdef __FreeBSD__
+ struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
+ struct inpcb *inp)
+#else
struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm)
+#endif
{
struct pf_rule *nr = NULL;
struct pf_addr *saddr = pd->src, *daddr = pd->dst;
@@ -2742,12 +2776,20 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
else if ((r->flagset & th->th_flags) != r->flags)
r = TAILQ_NEXT(r, entries);
else if (r->uid.op && (lookup != -1 || (lookup =
+#ifdef __FreeBSD__
+ pf_socket_lookup(&uid, &gid, direction, pd, inp), 1)) &&
+#else
pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
+#endif
!pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
uid))
r = TAILQ_NEXT(r, entries);
else if (r->gid.op && (lookup != -1 || (lookup =
+#ifdef __FreeBSD__
+ pf_socket_lookup(&uid, &gid, direction, pd, inp), 1)) &&
+#else
pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
+#endif
!pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
gid))
r = TAILQ_NEXT(r, entries);
@@ -3023,7 +3065,12 @@ cleanup:
int
pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
struct pfi_kif *kif, struct mbuf *m, int off, void *h,
+#ifdef __FreeBSD__
+ struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
+ struct inpcb *inp)
+#else
struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm)
+#endif
{
struct pf_rule *nr = NULL;
struct pf_addr *saddr = pd->src, *daddr = pd->dst;
@@ -3099,12 +3146,20 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
else if (r->rule_flag & PFRULE_FRAGMENT)
r = TAILQ_NEXT(r, entries);
else if (r->uid.op && (lookup != -1 || (lookup =
+#ifdef __FreeBSD__
+ pf_socket_lookup(&uid, &gid, direction, pd, inp), 1)) &&
+#else
pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
+#endif
!pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
uid))
r = TAILQ_NEXT(r, entries);
else if (r->gid.op && (lookup != -1 || (lookup =
+#ifdef __FreeBSD__
+ pf_socket_lookup(&uid, &gid, direction, pd, inp), 1)) &&
+#else
pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
+#endif
!pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
gid))
r = TAILQ_NEXT(r, entries);
@@ -5229,7 +5284,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
if (oifp != ifp) {
#ifdef __FreeBSD__
PF_UNLOCK();
- if (pf_test(PF_OUT, ifp, &m0) != PF_PASS) {
+ if (pf_test(PF_OUT, ifp, &m0, NULL) != PF_PASS) {
PF_LOCK();
goto bad;
} else if (m0 == NULL) {
@@ -5519,7 +5574,7 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
if (oifp != ifp) {
#ifdef __FreeBSD__
PF_UNLOCK();
- if (pf_test6(PF_OUT, ifp, &m0) != PF_PASS) {
+ if (pf_test6(PF_OUT, ifp, &m0, NULL) != PF_PASS) {
PF_LOCK();
goto bad;
} else if (m0 == NULL) {
@@ -5811,7 +5866,11 @@ pf_add_mbuf_tag(struct mbuf *m, u_int tag)
#ifdef INET
int
+#ifdef __FreeBSD__
+pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
+#else
pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
+#endif
{
struct pfi_kif *kif;
u_short action, reason = 0, log = 0;
@@ -5925,8 +5984,13 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
+#ifdef __FreeBSD__
+ action = pf_test_tcp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, inp);
+#else
action = pf_test_tcp(&r, &s, dir, kif,
m, off, h, &pd, &a, &ruleset);
+#endif
break;
}
@@ -5959,8 +6023,13 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
+#ifdef __FreeBSD__
+ action = pf_test_udp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, inp);
+#else
action = pf_test_udp(&r, &s, dir, kif,
m, off, h, &pd, &a, &ruleset);
+#endif
break;
}
@@ -6137,7 +6206,11 @@ done:
#ifdef INET6
int
+#ifdef __FreeBSD__
+pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
+#else
pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
+#endif
{
struct pfi_kif *kif;
u_short action, reason = 0, log = 0;
@@ -6274,8 +6347,13 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
+#ifdef __FreeBSD__
+ action = pf_test_tcp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, inp);
+#else
action = pf_test_tcp(&r, &s, dir, kif,
m, off, h, &pd, &a, &ruleset);
+#endif
break;
}
@@ -6308,8 +6386,13 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
+#ifdef __FreeBSD__
+ action = pf_test_udp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, inp);
+#else
action = pf_test_udp(&r, &s, dir, kif,
m, off, h, &pd, &a, &ruleset);
+#endif
break;
}
diff --git a/sys/contrib/pf/net/pf_ioctl.c b/sys/contrib/pf/net/pf_ioctl.c
index 9e173ba..4767dee 100644
--- a/sys/contrib/pf/net/pf_ioctl.c
+++ b/sys/contrib/pf/net/pf_ioctl.c
@@ -182,14 +182,14 @@ static void pf_clear_srcnodes(void);
* Wrapper functions for pfil(9) hooks
*/
static int pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp,
- int dir);
+ int dir, struct inpcb *inp);
static int pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp,
- int dir);
+ int dir, struct inpcb *inp);
#ifdef INET6
static int pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp,
- int dir);
+ int dir, struct inpcb *inp);
static int pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp,
- int dir);
+ int dir, struct inpcb *inp);
#endif
static int hook_pf(void);
@@ -3203,7 +3203,8 @@ shutdown_pf(void)
}
static int
-pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
+pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
{
/*
* XXX Wed Jul 9 22:03:16 2003 UTC
@@ -3222,7 +3223,7 @@ pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
HTONS(h->ip_len);
HTONS(h->ip_off);
}
- chk = pf_test(PF_IN, ifp, m);
+ chk = pf_test(PF_IN, ifp, m, inp);
if (chk && *m) {
m_freem(*m);
*m = NULL;
@@ -3237,7 +3238,8 @@ pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
}
static int
-pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
+pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
{
/*
* XXX Wed Jul 9 22:03:16 2003 UTC
@@ -3261,7 +3263,7 @@ pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
HTONS(h->ip_len);
HTONS(h->ip_off);
}
- chk = pf_test(PF_OUT, ifp, m);
+ chk = pf_test(PF_OUT, ifp, m, inp);
if (chk && *m) {
m_freem(*m);
*m = NULL;
@@ -3277,14 +3279,15 @@ pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
#ifdef INET6
static int
-pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
+pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
{
/*
* IPv6 does not affected ip_len/ip_off byte order changes.
*/
int chk;
- chk = pf_test6(PF_IN, ifp, m);
+ chk = pf_test6(PF_IN, ifp, m, inp);
if (chk && *m) {
m_freem(*m);
*m = NULL;
@@ -3293,7 +3296,8 @@ pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
}
static int
-pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
+pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
{
/*
* IPv6 does not affected ip_len/ip_off byte order changes.
@@ -3305,7 +3309,7 @@ pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
in_delayed_cksum(*m);
(*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
}
- chk = pf_test6(PF_OUT, ifp, m);
+ chk = pf_test6(PF_OUT, ifp, m, inp);
if (chk && *m) {
m_freem(*m);
*m = NULL;
diff --git a/sys/contrib/pf/net/pfvar.h b/sys/contrib/pf/net/pfvar.h
index 11446f8..ab21c59 100644
--- a/sys/contrib/pf/net/pfvar.h
+++ b/sys/contrib/pf/net/pfvar.h
@@ -54,6 +54,9 @@
#include <netinet/tcp_fsm.h>
struct ip;
+#ifdef __FreeBSD__
+struct inpcb;
+#endif
#define PF_TCPS_PROXY_SRC ((TCP_NSTATES)+0)
#define PF_TCPS_PROXY_DST ((TCP_NSTATES)+1)
@@ -1453,11 +1456,19 @@ void pf_rm_rule(struct pf_rulequeue *,
struct pf_rule *);
#ifdef INET
+#ifdef __FreeBSD__
+int pf_test(int, struct ifnet *, struct mbuf **, struct inpcb *);
+#else
int pf_test(int, struct ifnet *, struct mbuf **);
+#endif
#endif /* INET */
#ifdef INET6
+#ifdef __FreeBSD__
+int pf_test6(int, struct ifnet *, struct mbuf **, struct inpcb *);
+#else
int pf_test6(int, struct ifnet *, struct mbuf **);
+#endif
void pf_poolmask(struct pf_addr *, struct pf_addr*,
struct pf_addr *, struct pf_addr *, u_int8_t);
void pf_addr_inc(struct pf_addr *, sa_family_t);
OpenPOWER on IntegriCloud