Bridged packets are supplied to the firewall with their IP header
in network byte order, but icmp_error() expects the IP header to be in host order and the code here did not perform the necessary swapping for the bridged case. This bug causes an "icmp_error: bad length" panic when certain length IP packets (e.g. ip_len == 0x100) are rejected by the firewall with an ICMP response. MFC after: 3 days
This commit is contained in:
parent
03a585553a
commit
ed1a13b18f
@ -1236,7 +1236,6 @@ again:
|
|||||||
/* Check if rule only valid for bridged packets */
|
/* Check if rule only valid for bridged packets */
|
||||||
if ((f->fw_flg & IP_FW_BRIDGED) != 0 && !(BRIDGED))
|
if ((f->fw_flg & IP_FW_BRIDGED) != 0 && !(BRIDGED))
|
||||||
continue;
|
continue;
|
||||||
#undef BRIDGED
|
|
||||||
|
|
||||||
if (oif) {
|
if (oif) {
|
||||||
/* Check direction outbound */
|
/* Check direction outbound */
|
||||||
@ -1628,6 +1627,11 @@ got_match:
|
|||||||
&& (proto != IPPROTO_ICMP || is_icmp_query(ip))
|
&& (proto != IPPROTO_ICMP || is_icmp_query(ip))
|
||||||
&& !((*m)->m_flags & (M_BCAST|M_MCAST))
|
&& !((*m)->m_flags & (M_BCAST|M_MCAST))
|
||||||
&& !IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
|
&& !IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
|
||||||
|
/* Must convert to host order for icmp_error() etc. */
|
||||||
|
if (BRIDGED) {
|
||||||
|
ip->ip_len = ntohs(ip->ip_len);
|
||||||
|
ip->ip_off = ntohs(ip->ip_off);
|
||||||
|
}
|
||||||
switch (f->fw_reject_code) {
|
switch (f->fw_reject_code) {
|
||||||
case IP_FW_REJECT_RST:
|
case IP_FW_REJECT_RST:
|
||||||
{
|
{
|
||||||
@ -1670,6 +1674,7 @@ dropit:
|
|||||||
* Finally, drop the packet.
|
* Finally, drop the packet.
|
||||||
*/
|
*/
|
||||||
return(IP_FW_PORT_DENY_FLAG);
|
return(IP_FW_PORT_DENY_FLAG);
|
||||||
|
#undef BRIDGED
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1136,9 +1136,15 @@ static void
|
|||||||
send_reject(struct ip_fw_args *args, int code, int offset, int ip_len)
|
send_reject(struct ip_fw_args *args, int code, int offset, int ip_len)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (code != ICMP_REJECT_RST) /* Send an ICMP unreach */
|
if (code != ICMP_REJECT_RST) { /* Send an ICMP unreach */
|
||||||
|
/* We need the IP header in host order for icmp_error(). */
|
||||||
|
if (args->eh != NULL) {
|
||||||
|
struct ip *ip = mtod(args->m, struct ip *);
|
||||||
|
ip->ip_len = ntohs(ip->ip_len);
|
||||||
|
ip->ip_off = ntohs(ip->ip_off);
|
||||||
|
}
|
||||||
icmp_error(args->m, ICMP_UNREACH, code, 0L, 0);
|
icmp_error(args->m, ICMP_UNREACH, code, 0L, 0);
|
||||||
else if (offset == 0 && args->f_id.proto == IPPROTO_TCP) {
|
} else if (offset == 0 && args->f_id.proto == IPPROTO_TCP) {
|
||||||
struct tcphdr *const tcp =
|
struct tcphdr *const tcp =
|
||||||
L3HDR(struct tcphdr, mtod(args->m, struct ip *));
|
L3HDR(struct tcphdr, mtod(args->m, struct ip *));
|
||||||
if ( (tcp->th_flags & TH_RST) == 0)
|
if ( (tcp->th_flags & TH_RST) == 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user