wl3501_cs: Fix out-of-bounds warnings in wl3501_send_pkt
Fix the following out-of-bounds warnings by enclosing structure members daddr and saddr into new struct addr, in structures wl3501_md_req and wl3501_md_ind: arch/x86/include/asm/string_32.h:182:25: warning: '__builtin_memcpy' offset [18, 23] from the object at 'sig' is out of the bounds of referenced subobject 'daddr' with type 'u8[6]' {aka 'unsigned char[6]'} at offset 11 [-Warray-bounds] arch/x86/include/asm/string_32.h:182:25: warning: '__builtin_memcpy' offset [18, 23] from the object at 'sig' is out of the bounds of referenced subobject 'daddr' with type 'u8[6]' {aka 'unsigned char[6]'} at offset 11 [-Warray-bounds] Refactor the code, accordingly: $ pahole -C wl3501_md_req drivers/net/wireless/wl3501_cs.o struct wl3501_md_req { u16 next_blk; /* 0 2 */ u8 sig_id; /* 2 1 */ u8 routing; /* 3 1 */ u16 data; /* 4 2 */ u16 size; /* 6 2 */ u8 pri; /* 8 1 */ u8 service_class; /* 9 1 */ struct { u8 daddr[6]; /* 10 6 */ u8 saddr[6]; /* 16 6 */ } addr; /* 10 12 */ /* size: 22, cachelines: 1, members: 8 */ /* last cacheline: 22 bytes */ }; $ pahole -C wl3501_md_ind drivers/net/wireless/wl3501_cs.o struct wl3501_md_ind { u16 next_blk; /* 0 2 */ u8 sig_id; /* 2 1 */ u8 routing; /* 3 1 */ u16 data; /* 4 2 */ u16 size; /* 6 2 */ u8 reception; /* 8 1 */ u8 pri; /* 9 1 */ u8 service_class; /* 10 1 */ struct { u8 daddr[6]; /* 11 6 */ u8 saddr[6]; /* 17 6 */ } addr; /* 11 12 */ /* size: 24, cachelines: 1, members: 9 */ /* padding: 1 */ /* last cacheline: 24 bytes */ }; The problem is that the original code is trying to copy data into a couple of arrays adjacent to each other in a single call to memcpy(). Now that a new struct _addr_ enclosing those two adjacent arrays is introduced, memcpy() doesn't overrun the length of &sig.daddr[0] and &sig.daddr, because the address of the new struct object _addr_ is used, instead. This helps with the ongoing efforts to globally enable -Warray-bounds and get us closer to being able to tighten the FORTIFY_SOURCE routines on memcpy(). Link: https://github.com/KSPP/linux/issues/109 Reported-by: kernel test robot <lkp@intel.com> Reviewed-by: Kees Cook <keescook@chromium.org> Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org> Signed-off-by: Kalle Valo <kvalo@codeaurora.org> Link: https://lore.kernel.org/r/d260fe56aed7112bff2be5b4d152d03ad7b78e78.1618442265.git.gustavoars@kernel.org
This commit is contained in:
parent
ff9f732a87
commit
820aa37638
|
@ -471,8 +471,10 @@ struct wl3501_md_req {
|
|||
u16 size;
|
||||
u8 pri;
|
||||
u8 service_class;
|
||||
u8 daddr[ETH_ALEN];
|
||||
u8 saddr[ETH_ALEN];
|
||||
struct {
|
||||
u8 daddr[ETH_ALEN];
|
||||
u8 saddr[ETH_ALEN];
|
||||
} addr;
|
||||
};
|
||||
|
||||
struct wl3501_md_ind {
|
||||
|
@ -484,8 +486,10 @@ struct wl3501_md_ind {
|
|||
u8 reception;
|
||||
u8 pri;
|
||||
u8 service_class;
|
||||
u8 daddr[ETH_ALEN];
|
||||
u8 saddr[ETH_ALEN];
|
||||
struct {
|
||||
u8 daddr[ETH_ALEN];
|
||||
u8 saddr[ETH_ALEN];
|
||||
} addr;
|
||||
};
|
||||
|
||||
struct wl3501_md_confirm {
|
||||
|
|
|
@ -469,6 +469,7 @@ static int wl3501_send_pkt(struct wl3501_card *this, u8 *data, u16 len)
|
|||
struct wl3501_md_req sig = {
|
||||
.sig_id = WL3501_SIG_MD_REQ,
|
||||
};
|
||||
size_t sig_addr_len = sizeof(sig.addr);
|
||||
u8 *pdata = (char *)data;
|
||||
int rc = -EIO;
|
||||
|
||||
|
@ -484,9 +485,9 @@ static int wl3501_send_pkt(struct wl3501_card *this, u8 *data, u16 len)
|
|||
goto out;
|
||||
}
|
||||
rc = 0;
|
||||
memcpy(&sig.daddr[0], pdata, 12);
|
||||
pktlen = len - 12;
|
||||
pdata += 12;
|
||||
memcpy(&sig.addr, pdata, sig_addr_len);
|
||||
pktlen = len - sig_addr_len;
|
||||
pdata += sig_addr_len;
|
||||
sig.data = bf;
|
||||
if (((*pdata) * 256 + (*(pdata + 1))) > 1500) {
|
||||
u8 addr4[ETH_ALEN] = {
|
||||
|
@ -980,7 +981,8 @@ static inline void wl3501_md_ind_interrupt(struct net_device *dev,
|
|||
} else {
|
||||
skb->dev = dev;
|
||||
skb_reserve(skb, 2); /* IP headers on 16 bytes boundaries */
|
||||
skb_copy_to_linear_data(skb, (unsigned char *)&sig.daddr, 12);
|
||||
skb_copy_to_linear_data(skb, (unsigned char *)&sig.addr,
|
||||
sizeof(sig.addr));
|
||||
wl3501_receive(this, skb->data, pkt_len);
|
||||
skb_put(skb, pkt_len);
|
||||
skb->protocol = eth_type_trans(skb, dev);
|
||||
|
|
Loading…
Reference in New Issue