Introduce a new entry point, mac_create_mbuf_from_firewall. This entry point
exists to allow the mandatory access control policy to properly initialize mbufs generated by the firewall. An example where this might happen is keep alive packets, or ICMP error packets in response to other packets. This takes care of kernel panics associated with un-initialize mbuf labels when the firewall generates packets. [1] I modified this patch from it's original version, the initial patch introduced a number of entry points which were programmatically equivalent. So I introduced only one. Instead, we should leverage mac_create_mbuf_netlayer() which is used for similar situations, an example being icmp_error() This will minimize the impact associated with the MFC Submitted by: mlaier [1] MFC after: 1 week This is a RELENG_6 candidate
This commit is contained in:
parent
3bb00f61a2
commit
d94f2a68f8
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=162238
@ -42,6 +42,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include "opt_mac.h"
|
||||
#include "opt_bpf.h"
|
||||
#include "opt_pf.h"
|
||||
|
||||
@ -78,6 +79,7 @@
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/mac.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/endian.h>
|
||||
#else
|
||||
@ -192,7 +194,12 @@ void pf_change_icmp(struct pf_addr *, u_int16_t *,
|
||||
struct pf_addr *, struct pf_addr *, u_int16_t,
|
||||
u_int16_t *, u_int16_t *, u_int16_t *,
|
||||
u_int16_t *, u_int8_t, sa_family_t);
|
||||
#ifdef __FreeBSD__
|
||||
void pf_send_tcp(struct mbuf *,
|
||||
const struct pf_rule *, sa_family_t,
|
||||
#else
|
||||
void pf_send_tcp(const struct pf_rule *, sa_family_t,
|
||||
#endif
|
||||
const struct pf_addr *, const struct pf_addr *,
|
||||
u_int16_t, u_int16_t, u_int32_t, u_int32_t,
|
||||
u_int8_t, u_int16_t, u_int16_t, u_int8_t, int,
|
||||
@ -1114,7 +1121,11 @@ pf_purge_expired_state(struct pf_state *cur)
|
||||
cur->local_flags |= PFSTATE_EXPIRING;
|
||||
#endif
|
||||
if (cur->src.state == PF_TCPS_PROXY_DST)
|
||||
#ifdef __FreeBSD__
|
||||
pf_send_tcp(NULL, cur->rule.ptr, cur->af,
|
||||
#else
|
||||
pf_send_tcp(cur->rule.ptr, cur->af,
|
||||
#endif
|
||||
&cur->ext.addr, &cur->lan.addr,
|
||||
cur->ext.port, cur->lan.port,
|
||||
cur->src.seqhi, cur->src.seqlo + 1,
|
||||
@ -1574,7 +1585,11 @@ pf_change_icmp(struct pf_addr *ia, u_int16_t *ip, struct pf_addr *oa,
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef __FreeBSD__
|
||||
pf_send_tcp(struct mbuf *replyto, const struct pf_rule *r, sa_family_t af,
|
||||
#else
|
||||
pf_send_tcp(const struct pf_rule *r, sa_family_t af,
|
||||
#endif
|
||||
const struct pf_addr *saddr, const struct pf_addr *daddr,
|
||||
u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack,
|
||||
u_int8_t flags, u_int16_t win, u_int16_t mss, u_int8_t ttl, int tag,
|
||||
@ -1613,6 +1628,16 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af,
|
||||
m = m_gethdr(M_DONTWAIT, MT_HEADER);
|
||||
if (m == NULL)
|
||||
return;
|
||||
#ifdef __FreeBSD__
|
||||
#ifdef MAC
|
||||
if (replyto)
|
||||
mac_create_mbuf_netlayer(replyto, m);
|
||||
else
|
||||
mac_create_mbuf_from_firewall(m);
|
||||
#else
|
||||
(void)replyto;
|
||||
#endif
|
||||
#endif
|
||||
if (tag) {
|
||||
#ifdef __FreeBSD__
|
||||
m->m_flags |= M_SKIP_FIREWALL;
|
||||
@ -3146,7 +3171,11 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
|
||||
ack++;
|
||||
if (th->th_flags & TH_FIN)
|
||||
ack++;
|
||||
#ifdef __FreeBSD__
|
||||
pf_send_tcp(m, r, af, pd->dst,
|
||||
#else
|
||||
pf_send_tcp(r, af, pd->dst,
|
||||
#endif
|
||||
pd->src, th->th_dport, th->th_sport,
|
||||
ntohl(th->th_ack), ack, TH_RST|TH_ACK, 0, 0,
|
||||
r->return_ttl, 1, pd->eh, kif->pfik_ifp);
|
||||
@ -3347,7 +3376,11 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
|
||||
mss = pf_calc_mss(saddr, af, mss);
|
||||
mss = pf_calc_mss(daddr, af, mss);
|
||||
s->src.mss = mss;
|
||||
#ifdef __FreeBSD__
|
||||
pf_send_tcp(NULL, r, af, daddr, saddr, th->th_dport,
|
||||
#else
|
||||
pf_send_tcp(r, af, daddr, saddr, th->th_dport,
|
||||
#endif
|
||||
th->th_sport, s->src.seqhi, ntohl(th->th_seq) + 1,
|
||||
TH_SYN|TH_ACK, 0, s->src.mss, 0, 1, NULL, NULL);
|
||||
REASON_SET(&reason, PFRES_SYNPROXY);
|
||||
@ -4348,7 +4381,11 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
|
||||
REASON_SET(reason, PFRES_SYNPROXY);
|
||||
return (PF_DROP);
|
||||
}
|
||||
#ifdef __FreeBSD__
|
||||
pf_send_tcp(NULL, (*state)->rule.ptr, pd->af, pd->dst,
|
||||
#else
|
||||
pf_send_tcp((*state)->rule.ptr, pd->af, pd->dst,
|
||||
#endif
|
||||
pd->src, th->th_dport, th->th_sport,
|
||||
(*state)->src.seqhi, ntohl(th->th_seq) + 1,
|
||||
TH_SYN|TH_ACK, 0, (*state)->src.mss, 0, 1,
|
||||
@ -4387,7 +4424,12 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
|
||||
(*state)->src.max_win = MAX(ntohs(th->th_win), 1);
|
||||
if ((*state)->dst.seqhi == 1)
|
||||
(*state)->dst.seqhi = htonl(arc4random());
|
||||
#ifdef __FreeBSD__
|
||||
pf_send_tcp(NULL, (*state)->rule.ptr, pd->af,
|
||||
&src->addr,
|
||||
#else
|
||||
pf_send_tcp((*state)->rule.ptr, pd->af, &src->addr,
|
||||
#endif
|
||||
&dst->addr, src->port, dst->port,
|
||||
(*state)->dst.seqhi, 0, TH_SYN, 0,
|
||||
(*state)->src.mss, 0, 0, NULL, NULL);
|
||||
@ -4401,12 +4443,21 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
|
||||
} else {
|
||||
(*state)->dst.max_win = MAX(ntohs(th->th_win), 1);
|
||||
(*state)->dst.seqlo = ntohl(th->th_seq);
|
||||
#ifdef __FreeBSD__
|
||||
pf_send_tcp(NULL, (*state)->rule.ptr, pd->af, pd->dst,
|
||||
#else
|
||||
pf_send_tcp((*state)->rule.ptr, pd->af, pd->dst,
|
||||
#endif
|
||||
pd->src, th->th_dport, th->th_sport,
|
||||
ntohl(th->th_ack), ntohl(th->th_seq) + 1,
|
||||
TH_ACK, (*state)->src.max_win, 0, 0, 0,
|
||||
NULL, NULL);
|
||||
#ifdef __FreeBSD__
|
||||
pf_send_tcp(NULL, (*state)->rule.ptr, pd->af,
|
||||
&src->addr,
|
||||
#else
|
||||
pf_send_tcp((*state)->rule.ptr, pd->af, &src->addr,
|
||||
#endif
|
||||
&dst->addr, src->port, dst->port,
|
||||
(*state)->src.seqhi + 1, (*state)->src.seqlo + 1,
|
||||
TH_ACK, (*state)->dst.max_win, 0, 0, 1,
|
||||
@ -4685,7 +4736,11 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
|
||||
(*state)->src.state == TCPS_SYN_SENT) {
|
||||
/* Send RST for state mismatches during handshake */
|
||||
if (!(th->th_flags & TH_RST))
|
||||
#ifdef __FreeBSD__
|
||||
pf_send_tcp(m, (*state)->rule.ptr, pd->af,
|
||||
#else
|
||||
pf_send_tcp((*state)->rule.ptr, pd->af,
|
||||
#endif
|
||||
pd->dst, pd->src, th->th_dport,
|
||||
th->th_sport, ntohl(th->th_ack), 0,
|
||||
TH_RST, 0, 0,
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
KMOD= ipfw
|
||||
SRCS= ip_fw2.c ip_fw_pfil.c
|
||||
SRCS+= opt_inet6.h opt_ipsec.h
|
||||
SRCS+= opt_inet6.h opt_ipsec.h opt_mac.h
|
||||
|
||||
CFLAGS+= -DIPFIREWALL
|
||||
#
|
||||
|
@ -8,7 +8,7 @@
|
||||
KMOD= pf
|
||||
SRCS = pf.c pf_if.c pf_subr.c pf_osfp.c pf_ioctl.c pf_norm.c pf_table.c \
|
||||
in4_cksum.c \
|
||||
opt_pf.h opt_inet.h opt_inet6.h opt_bpf.h
|
||||
opt_pf.h opt_inet.h opt_inet6.h opt_bpf.h opt_mac.h
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/../../contrib/pf
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#endif
|
||||
#include "opt_inet6.h"
|
||||
#include "opt_ipsec.h"
|
||||
#include "opt_mac.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -51,6 +52,7 @@
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/mac.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/rwlock.h>
|
||||
@ -1541,9 +1543,12 @@ install_state(struct ip_fw *rule, ipfw_insn_limit *cmd,
|
||||
* When flags & TH_RST, we are sending a RST packet, because of a
|
||||
* "reset" action matched the packet.
|
||||
* Otherwise we are sending a keepalive, and flags & TH_
|
||||
* The 'replyto' mbuf is the mbuf being replied to, if any, and is required
|
||||
* so that MAC can label the reply appropriately.
|
||||
*/
|
||||
static struct mbuf *
|
||||
send_pkt(struct ipfw_flow_id *id, u_int32_t seq, u_int32_t ack, int flags)
|
||||
send_pkt(struct mbuf *replyto, struct ipfw_flow_id *id, u_int32_t seq,
|
||||
u_int32_t ack, int flags)
|
||||
{
|
||||
struct mbuf *m;
|
||||
struct ip *ip;
|
||||
@ -1553,6 +1558,16 @@ send_pkt(struct ipfw_flow_id *id, u_int32_t seq, u_int32_t ack, int flags)
|
||||
if (m == 0)
|
||||
return (NULL);
|
||||
m->m_pkthdr.rcvif = (struct ifnet *)0;
|
||||
|
||||
#ifdef MAC
|
||||
if (replyto != NULL)
|
||||
mac_create_mbuf_netlayer(replyto, m);
|
||||
else
|
||||
mac_create_mbuf_from_firewall(m);
|
||||
#else
|
||||
(void)replyto; /* don't warn about unused arg */
|
||||
#endif
|
||||
|
||||
m->m_pkthdr.len = m->m_len = sizeof(struct ip) + sizeof(struct tcphdr);
|
||||
m->m_data += max_linkhdr;
|
||||
|
||||
@ -1637,8 +1652,8 @@ send_reject(struct ip_fw_args *args, int code, int ip_len)
|
||||
L3HDR(struct tcphdr, mtod(args->m, struct ip *));
|
||||
if ( (tcp->th_flags & TH_RST) == 0) {
|
||||
struct mbuf *m;
|
||||
m = send_pkt(&(args->f_id), ntohl(tcp->th_seq),
|
||||
ntohl(tcp->th_ack),
|
||||
m = send_pkt(args->m, &(args->f_id),
|
||||
ntohl(tcp->th_seq), ntohl(tcp->th_ack),
|
||||
tcp->th_flags | TH_RST);
|
||||
if (m != NULL)
|
||||
ip_output(m, NULL, NULL, 0, NULL, NULL);
|
||||
@ -4185,11 +4200,11 @@ ipfw_tick(void * __unused unused)
|
||||
if (TIME_LEQ(q->expire, time_uptime))
|
||||
continue; /* too late, rule expired */
|
||||
|
||||
*mtailp = send_pkt(&(q->id), q->ack_rev - 1,
|
||||
*mtailp = send_pkt(NULL, &(q->id), q->ack_rev - 1,
|
||||
q->ack_fwd, TH_SYN);
|
||||
if (*mtailp != NULL)
|
||||
mtailp = &(*mtailp)->m_nextpkt;
|
||||
*mtailp = send_pkt(&(q->id), q->ack_fwd - 1,
|
||||
*mtailp = send_pkt(NULL, &(q->id), q->ack_fwd - 1,
|
||||
q->ack_rev, 0);
|
||||
if (*mtailp != NULL)
|
||||
mtailp = &(*mtailp)->m_nextpkt;
|
||||
|
@ -267,6 +267,7 @@ void mac_reflect_mbuf_tcp(struct mbuf *m);
|
||||
void mac_update_ipq(struct mbuf *fragment, struct ipq *ipq);
|
||||
void mac_inpcb_sosetlabel(struct socket *so, struct inpcb *inp);
|
||||
|
||||
void mac_create_mbuf_from_firewall(struct mbuf *m);
|
||||
/*
|
||||
* Labeling event operations: processes.
|
||||
*/
|
||||
|
@ -290,3 +290,13 @@ mac_inpcb_sosetlabel(struct socket *so, struct inpcb *inp)
|
||||
INP_LOCK_ASSERT(inp);
|
||||
MAC_PERFORM(inpcb_sosetlabel, so, so->so_label, inp, inp->inp_label);
|
||||
}
|
||||
|
||||
void
|
||||
mac_create_mbuf_from_firewall(struct mbuf *m)
|
||||
{
|
||||
struct label *label;
|
||||
|
||||
M_ASSERTPKTHDR(m);
|
||||
label = mac_mbuf_to_label(m);
|
||||
MAC_PERFORM(create_mbuf_from_firewall, m, label);
|
||||
}
|
||||
|
@ -326,6 +326,8 @@ typedef void (*mpo_inpcb_sosetlabel_t)(struct socket *so,
|
||||
struct label *label, struct inpcb *inp,
|
||||
struct label *inplabel);
|
||||
|
||||
typedef void (*mpo_create_mbuf_from_firewall_t)(struct mbuf *m,
|
||||
struct label *label);
|
||||
/*
|
||||
* Labeling event operations: processes.
|
||||
*/
|
||||
@ -880,6 +882,7 @@ struct mac_policy_ops {
|
||||
mpo_check_vnode_stat_t mpo_check_vnode_stat;
|
||||
mpo_check_vnode_write_t mpo_check_vnode_write;
|
||||
mpo_associate_nfsd_label_t mpo_associate_nfsd_label;
|
||||
mpo_create_mbuf_from_firewall_t mpo_create_mbuf_from_firewall;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1381,6 +1381,17 @@ mac_biba_inpcb_sosetlabel(struct socket *so, struct label *solabel,
|
||||
mac_biba_copy(source, dest);
|
||||
}
|
||||
|
||||
static void
|
||||
mac_biba_create_mbuf_from_firewall(struct mbuf *m, struct label *label)
|
||||
{
|
||||
struct mac_biba *dest;
|
||||
|
||||
dest = SLOT(label);
|
||||
|
||||
/* XXX: where is the label for the firewall really comming from? */
|
||||
mac_biba_set_effective(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Labeling event operations: processes.
|
||||
*/
|
||||
@ -3210,6 +3221,7 @@ static struct mac_policy_ops mac_biba_ops =
|
||||
.mpo_check_vnode_stat = mac_biba_check_vnode_stat,
|
||||
.mpo_check_vnode_write = mac_biba_check_vnode_write,
|
||||
.mpo_associate_nfsd_label = mac_biba_associate_nfsd_label,
|
||||
.mpo_create_mbuf_from_firewall = mac_biba_create_mbuf_from_firewall,
|
||||
};
|
||||
|
||||
MAC_POLICY_SET(&mac_biba_ops, mac_biba, "TrustedBSD MAC/Biba",
|
||||
|
@ -1446,6 +1446,17 @@ mac_lomac_inpcb_sosetlabel(struct socket *so, struct label *solabel,
|
||||
mac_lomac_copy_single(source, dest);
|
||||
}
|
||||
|
||||
static void
|
||||
mac_lomac_create_mbuf_from_firewall(struct mbuf *m, struct label *label)
|
||||
{
|
||||
struct mac_lomac *dest;
|
||||
|
||||
dest = SLOT(label);
|
||||
|
||||
/* XXX: where is the label for the firewall really comming from? */
|
||||
mac_lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Labeling event operations: processes.
|
||||
*/
|
||||
@ -2685,6 +2696,7 @@ static struct mac_policy_ops mac_lomac_ops =
|
||||
.mpo_check_vnode_setutimes = mac_lomac_check_vnode_setutimes,
|
||||
.mpo_check_vnode_write = mac_lomac_check_vnode_write,
|
||||
.mpo_thread_userret = mac_lomac_thread_userret,
|
||||
.mpo_create_mbuf_from_firewall = mac_lomac_create_mbuf_from_firewall,
|
||||
};
|
||||
|
||||
MAC_POLICY_SET(&mac_lomac_ops, mac_lomac, "TrustedBSD MAC/LOMAC",
|
||||
|
@ -1305,6 +1305,17 @@ mac_mls_inpcb_sosetlabel(struct socket *so, struct label *solabel,
|
||||
mac_mls_copy(source, dest);
|
||||
}
|
||||
|
||||
static void
|
||||
mac_mls_create_mbuf_from_firewall(struct mbuf *m, struct label *mbuflabel)
|
||||
{
|
||||
struct mac_mls *dest;
|
||||
|
||||
dest = SLOT(mbuflabel);
|
||||
|
||||
/* XXX: where is the label for the firewall really comming from? */
|
||||
mac_mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Labeling event operations: processes.
|
||||
*/
|
||||
@ -2972,6 +2983,7 @@ static struct mac_policy_ops mac_mls_ops =
|
||||
.mpo_check_vnode_stat = mac_mls_check_vnode_stat,
|
||||
.mpo_check_vnode_write = mac_mls_check_vnode_write,
|
||||
.mpo_associate_nfsd_label = mac_mls_associate_nfsd_label,
|
||||
.mpo_create_mbuf_from_firewall = mac_mls_create_mbuf_from_firewall,
|
||||
};
|
||||
|
||||
MAC_POLICY_SET(&mac_mls_ops, mac_mls, "TrustedBSD MAC/MLS",
|
||||
|
@ -267,6 +267,7 @@ void mac_reflect_mbuf_tcp(struct mbuf *m);
|
||||
void mac_update_ipq(struct mbuf *fragment, struct ipq *ipq);
|
||||
void mac_inpcb_sosetlabel(struct socket *so, struct inpcb *inp);
|
||||
|
||||
void mac_create_mbuf_from_firewall(struct mbuf *m);
|
||||
/*
|
||||
* Labeling event operations: processes.
|
||||
*/
|
||||
|
@ -326,6 +326,8 @@ typedef void (*mpo_inpcb_sosetlabel_t)(struct socket *so,
|
||||
struct label *label, struct inpcb *inp,
|
||||
struct label *inplabel);
|
||||
|
||||
typedef void (*mpo_create_mbuf_from_firewall_t)(struct mbuf *m,
|
||||
struct label *label);
|
||||
/*
|
||||
* Labeling event operations: processes.
|
||||
*/
|
||||
@ -880,6 +882,7 @@ struct mac_policy_ops {
|
||||
mpo_check_vnode_stat_t mpo_check_vnode_stat;
|
||||
mpo_check_vnode_write_t mpo_check_vnode_write;
|
||||
mpo_associate_nfsd_label_t mpo_associate_nfsd_label;
|
||||
mpo_create_mbuf_from_firewall_t mpo_create_mbuf_from_firewall;
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user