Source-Changes-D archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: CVS commit: src/sys/dev/hyperv
> Module Name: src
> Committed By: joe
> Date: Sun Feb 16 15:56:06 UTC 2025
>
> Modified Files:
> src/sys/dev/hyperv: if_hvn.c
>
> Log Message:
> avoid buffer overflow when copying the ether header host into the ether vland header host
> on hyper-v
> [...]
> @@ -1697,7 +1697,7 @@ hvn_bpf_mtap(struct hvn_tx_ring *txr, st
> */
>
> eh = mtod(m, struct ether_header *);
> - memcpy(evl.evl_dhost, eh->ether_dhost, ETHER_ADDR_LEN * 2);
> + memcpy(evl.evl_dhost, eh->ether_dhost, ETHER_ADDR_LEN);
> evl.evl_encap_proto = htons(ETHERTYPE_VLAN);
> evl.evl_tag = htons(vlan_get_tag(m));
> evl.evl_proto = eh->ether_type;
> @@ -4836,7 +4836,7 @@ hvn_rxeof(struct hvn_rx_ring *rxr, uint8
>
> evl = mtod(m, struct ether_vlan_header *);
> memcpy(evl->evl_dhost, eh.ether_dhost,
> - ETHER_ADDR_LEN * 2);
> + ETHER_ADDR_LEN);
I think this change is not correct and should be either reverted or
done differently. There is no buffer overrun here because of the
shape of struct ether_vlan_header and struct ether_header:
struct ether_vlan_header {
uint8_t evl_dhost[ETHER_ADDR_LEN];
uint8_t evl_shost[ETHER_ADDR_LEN];
uint16_t evl_encap_proto;
uint16_t evl_tag;
uint16_t evl_proto;
} __packed;
struct ether_header {
uint8_t ether_dhost[ETHER_ADDR_LEN];
uint8_t ether_shost[ETHER_ADDR_LEN];
uint16_t ether_type;
};
So there are two consecutive ETHER_ADDR_LEN-byte arrays starting at
evl.evl_dhost and eh->ether_dhost, and we need to copy _both_ of them
(the destination and source addresses).
It is likely that static analyzers don't like this because, without
the context, it looks like a buffer overrun: the input to memcpy is
formally an array of length ETHER_ADDR_LEN.
But since there is no padding in either structure[*], there is another
array of length ETHER_ADDR_LEN consecutive in memory, so this is not
actually a buffer overrun. And copying only the destination address,
not the source address, will certainly break this driver.
If you want to pacify the static analyzers without breaking the
functionality, I suggest writing two memcpy calls:
memcpy(evl.evl_dhost, eh->ether_dhost, ETHER_ADDR_LEN);
memcpy(evl.evl_shost, eh->ether_shost, ETHER_ADDR_LEN);
Just be careful of applying the suggestions of static analyzers --
they are not always right! I suggest you ask for review before making
changes like this, especially if you don't have the hardware (or, in
this case, host software) to test the driver. You can file a PR with
the proposed change to help keep track -- and that will also help to
track pullups in case netbsd-9 or netbsd-10 also need fixes.
[*] struct ether_header used to be marked __packed, but roy@ removed
that back in 2021:
https://mail-index.netbsd.org/source-changes/2021/02/03/msg126553.html
He put a __CTASSERT of the size in to ensure the build fails if
the compiler ever inserts any padding (I think I may have
requested that):
https://mail-index.netbsd.org/source-changes/2021/02/03/msg126567.html
https://mail-index.netbsd.org/source-changes/2021/02/03/msg126578.html
But then removed it while removing some alignment checks, for
reasons unclear to me:
https://mail-index.netbsd.org/source-changes/2021/02/14/msg126887.html
In any case, whether or not we have a static assertion to verify
the size, none of our ethernet drivers would function if struct
ether_header had any padding in it!
Home |
Main Index |
Thread Index |
Old Index