Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

orinoco: Avoid field-overflowing memcpy()

In preparation for FORTIFY_SOURCE performing compile-time and run-time
field bounds checking for memcpy(), memmove(), and memset(), avoid
intentionally writing across neighboring array fields.

Validate the expected key size and introduce a wrapping structure
to use as the multi-field memcpy() destination so that overflows
can be correctly detected.

Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20210616203952.1248910-1-keescook@chromium.org

authored by

Kees Cook and committed by
Kalle Valo
70ca8441 b38678a7

+15 -10
+11 -7
drivers/net/wireless/intersil/orinoco/hw.c
··· 988 988 * tsc must be NULL or up to 8 bytes 989 989 */ 990 990 int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, 991 - int set_tx, const u8 *key, const u8 *rsc, 992 - size_t rsc_len, const u8 *tsc, size_t tsc_len) 991 + int set_tx, const u8 *key, size_t key_len, 992 + const u8 *rsc, size_t rsc_len, 993 + const u8 *tsc, size_t tsc_len) 993 994 { 994 995 struct { 995 996 __le16 idx; 996 997 u8 rsc[ORINOCO_SEQ_LEN]; 997 - u8 key[TKIP_KEYLEN]; 998 - u8 tx_mic[MIC_KEYLEN]; 999 - u8 rx_mic[MIC_KEYLEN]; 998 + struct { 999 + u8 key[TKIP_KEYLEN]; 1000 + u8 tx_mic[MIC_KEYLEN]; 1001 + u8 rx_mic[MIC_KEYLEN]; 1002 + } tkip; 1000 1003 u8 tsc[ORINOCO_SEQ_LEN]; 1001 1004 } __packed buf; 1002 1005 struct hermes *hw = &priv->hw; ··· 1014 1011 key_idx |= 0x8000; 1015 1012 1016 1013 buf.idx = cpu_to_le16(key_idx); 1017 - memcpy(buf.key, key, 1018 - sizeof(buf.key) + sizeof(buf.tx_mic) + sizeof(buf.rx_mic)); 1014 + if (key_len != sizeof(buf.tkip)) 1015 + return -EINVAL; 1016 + memcpy(&buf.tkip, key, sizeof(buf.tkip)); 1019 1017 1020 1018 if (rsc_len > sizeof(buf.rsc)) 1021 1019 rsc_len = sizeof(buf.rsc);
+3 -2
drivers/net/wireless/intersil/orinoco/hw.h
··· 38 38 int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv); 39 39 int __orinoco_hw_setup_enc(struct orinoco_private *priv); 40 40 int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, 41 - int set_tx, const u8 *key, const u8 *rsc, 42 - size_t rsc_len, const u8 *tsc, size_t tsc_len); 41 + int set_tx, const u8 *key, size_t key_len, 42 + const u8 *rsc, size_t rsc_len, 43 + const u8 *tsc, size_t tsc_len); 43 44 int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx); 44 45 int __orinoco_hw_set_multicast_list(struct orinoco_private *priv, 45 46 struct net_device *dev,
+1 -1
drivers/net/wireless/intersil/orinoco/wext.c
··· 791 791 792 792 err = __orinoco_hw_set_tkip_key(priv, idx, 793 793 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, 794 - priv->keys[idx].key, 794 + priv->keys[idx].key, priv->keys[idx].key_len, 795 795 tkip_iv, ORINOCO_SEQ_LEN, NULL, 0); 796 796 if (err) 797 797 printk(KERN_ERR "%s: Error %d setting TKIP key"