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

asix: Ensure asix_rx_fixup_info members are all reset

There is a risk that the members of the structure asix_rx_fixup_info
become unsynchronised leading to the possibility of a malfunction.

For example, rx->split_head was not being set to false after an
error was detected so potentially could cause a malformed 32-bit
Data header word to be formed.

Therefore add function reset_asix_rx_fixup_info() to reset all the
members of asix_rx_fixup_info so that future processing will start
with known initial conditions.

Also, if (skb->len != offset) becomes true then call
reset_asix_rx_fixup_info() so that the processing of the next URB
starts with known initial conditions. Without the call, the check
does nothing which potentially could lead to a malfunction
when the next URB is processed.

In addition, for robustness, call reset_asix_rx_fixup_info() before
every error path's "return 0". This ensures that the next URB is
processed from known initial conditions.

Signed-off-by: Dean Jenkins <Dean_Jenkins@mentor.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Dean Jenkins and committed by
David S. Miller
960eb4ee 22889dbb

+25 -9
+25 -9
drivers/net/usb/asix_common.c
··· 75 75 value, index, data, size); 76 76 } 77 77 78 + static void reset_asix_rx_fixup_info(struct asix_rx_fixup_info *rx) 79 + { 80 + /* Reset the variables that have a lifetime outside of 81 + * asix_rx_fixup_internal() so that future processing starts from a 82 + * known set of initial conditions. 83 + */ 84 + 85 + if (rx->ax_skb) { 86 + /* Discard any incomplete Ethernet frame in the netdev buffer */ 87 + kfree_skb(rx->ax_skb); 88 + rx->ax_skb = NULL; 89 + } 90 + 91 + /* Assume the Data header 32-bit word is at the start of the current 92 + * or next URB socket buffer so reset all the state variables. 93 + */ 94 + rx->remaining = 0; 95 + rx->split_head = false; 96 + rx->header = 0; 97 + } 98 + 78 99 int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, 79 100 struct asix_rx_fixup_info *rx) 80 101 { ··· 120 99 if (size != ((~rx->header >> 16) & 0x7ff)) { 121 100 netdev_err(dev->net, "asix_rx_fixup() Data Header synchronisation was lost, remaining %d\n", 122 101 rx->remaining); 123 - if (rx->ax_skb) { 124 - kfree_skb(rx->ax_skb); 125 - rx->ax_skb = NULL; 126 - /* Discard the incomplete netdev Ethernet frame 127 - * and assume the Data header is at the start of 128 - * the current URB socket buffer. 129 - */ 130 - } 131 - rx->remaining = 0; 102 + reset_asix_rx_fixup_info(rx); 132 103 } 133 104 } 134 105 ··· 152 139 if (size != ((~rx->header >> 16) & 0x7ff)) { 153 140 netdev_err(dev->net, "asix_rx_fixup() Bad Header Length 0x%x, offset %d\n", 154 141 rx->header, offset); 142 + reset_asix_rx_fixup_info(rx); 155 143 return 0; 156 144 } 157 145 if (size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) { 158 146 netdev_dbg(dev->net, "asix_rx_fixup() Bad RX Length %d\n", 159 147 size); 148 + reset_asix_rx_fixup_info(rx); 160 149 return 0; 161 150 } 162 151 ··· 195 180 if (skb->len != offset) { 196 181 netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d, %d\n", 197 182 skb->len, offset); 183 + reset_asix_rx_fixup_info(rx); 198 184 return 0; 199 185 } 200 186