[prev in list] [next in list] [prev in thread] [next in thread]
List: netfilter-devel
Subject: Bug in MAC address matching
From: "Erick C. Jones" <erick () baronservices ! com>
Date: 2001-08-30 2:20:00
[Download RAW message or body]
I don't really know much about this code, I'm just passing along a very small
bug that I think I fixed.
The MAC address match apparently fails when a packet is very small.
The following code from ipt_mac.c, around line 21, appears to be the culprit:
/* Is mac pointer valid? */
return (skb->mac.raw >= skb->head
&& skb->mac.raw < skb->head + skb->len - ETH_HLEN
/* If so, compare... */
(I'm testing this against the 2.4.2 kernel, but I checked and saw that
ipt_mac.c has not been changed in the latest kernel. My apologies if this
problem has already been fixed by a change elsewhere in the code.)
The pointer validity check apparently assumes that skb->len is the total
length of the area pointed to by skb->head. I'm not sure exactly what
skb->len is, but it's not that.
If I try to apply this rule to a 2-byte UDP packet (that is, the application's
sendto call only sends 2 bytes), skb->len is 30. (In general, it seems to be
28 plus the payload size.)
Does that mean that skb->head points to a 30-byte region? But the payload
itself actually starts at skb->head + 60!
What about the skb->end field? In the case of the 2-byte UDP packet, skb->end
- skb->head == 80, which seems a more reasonable measurement of the size (but
I'm just guessing here).
Regardless of what skb->len actually means, let's consider what it would take
for the conditions above to be met. "skb->mac.raw >= skb->head" should always
be true (unless we have corrupt data or something, I guess). But when will
"skb->mac.raw < skb->head + skb->len - ETH_HLEN" be true? I've found that
skb->mac.raw - skb->head == 18, so this simplifies to "18 < skb->len -
ETH_HLEN". And since skb->len is the payload size plus 28 and ETH_HLEN is 14,
we have "18 < 28 + p - 14", or "4 < p" (where p is the payload size). So this
condition will fail if the size of the payload is less than or equal to 4.
Anyway, I fixed this by simply implementing a more lenient validity check:
/* Is mac pointer valid? */
return (skb->mac.raw >= skb->head
&& skb->mac.raw + ETH_HLEN <= skb->end
/* If so, compare... */
Correct solution? Am I missing something?
Why do I even care about this? Well, I have two firewalls and two routers all
connected to a single hub, and each firewall must be able to determine whether
a given packet came from the other firewall or from a router. Since all the
hosts directly connected to the hub are trusted, the mac address seems like a
reliable indicator. (In other words, the routers themselves can be trusted to
correctly report their own mac addresses, even if the packets they're relaying
are from malevolent hackers; similarly, the other firewall will correctly
report its mac address, and a little more trust can be assigned to packets
from it because they must have come from inside the building.) Unfortunately,
PCAnywhere likes to initiate connections by sending a 2-byte UDP packet, and
it was failing the mac address check.
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic