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

arcnet: provide a buffer big enough to actually receive packets

struct archdr is only big enough to hold the header of various types of
arcnet packets. So to provide enough space to hold the data read from
hardware provide a buffer large enough to hold a packet with maximal
size.

The problem was noticed by the stack protector which makes the kernel
oops.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Acked-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Uwe Kleine-König and committed by
David S. Miller
02a07046 0edc3f70

+17 -14
+17 -14
drivers/net/arcnet/arcnet.c
··· 1063 1063 static void arcnet_rx(struct net_device *dev, int bufnum) 1064 1064 { 1065 1065 struct arcnet_local *lp = netdev_priv(dev); 1066 - struct archdr pkt; 1066 + union { 1067 + struct archdr pkt; 1068 + char buf[512]; 1069 + } rxdata; 1067 1070 struct arc_rfc1201 *soft; 1068 1071 int length, ofs; 1069 1072 1070 - soft = &pkt.soft.rfc1201; 1073 + soft = &rxdata.pkt.soft.rfc1201; 1071 1074 1072 - lp->hw.copy_from_card(dev, bufnum, 0, &pkt, ARC_HDR_SIZE); 1073 - if (pkt.hard.offset[0]) { 1074 - ofs = pkt.hard.offset[0]; 1075 + lp->hw.copy_from_card(dev, bufnum, 0, &rxdata.pkt, ARC_HDR_SIZE); 1076 + if (rxdata.pkt.hard.offset[0]) { 1077 + ofs = rxdata.pkt.hard.offset[0]; 1075 1078 length = 256 - ofs; 1076 1079 } else { 1077 - ofs = pkt.hard.offset[1]; 1080 + ofs = rxdata.pkt.hard.offset[1]; 1078 1081 length = 512 - ofs; 1079 1082 } 1080 1083 1081 1084 /* get the full header, if possible */ 1082 - if (sizeof(pkt.soft) <= length) { 1083 - lp->hw.copy_from_card(dev, bufnum, ofs, soft, sizeof(pkt.soft)); 1085 + if (sizeof(rxdata.pkt.soft) <= length) { 1086 + lp->hw.copy_from_card(dev, bufnum, ofs, soft, sizeof(rxdata.pkt.soft)); 1084 1087 } else { 1085 - memset(&pkt.soft, 0, sizeof(pkt.soft)); 1088 + memset(&rxdata.pkt.soft, 0, sizeof(rxdata.pkt.soft)); 1086 1089 lp->hw.copy_from_card(dev, bufnum, ofs, soft, length); 1087 1090 } 1088 1091 1089 1092 arc_printk(D_DURING, dev, "Buffer #%d: received packet from %02Xh to %02Xh (%d+4 bytes)\n", 1090 - bufnum, pkt.hard.source, pkt.hard.dest, length); 1093 + bufnum, rxdata.pkt.hard.source, rxdata.pkt.hard.dest, length); 1091 1094 1092 1095 dev->stats.rx_packets++; 1093 1096 dev->stats.rx_bytes += length + ARC_HDR_SIZE; ··· 1099 1096 if (arc_proto_map[soft->proto]->is_ip) { 1100 1097 if (BUGLVL(D_PROTO)) { 1101 1098 struct ArcProto 1102 - *oldp = arc_proto_map[lp->default_proto[pkt.hard.source]], 1099 + *oldp = arc_proto_map[lp->default_proto[rxdata.pkt.hard.source]], 1103 1100 *newp = arc_proto_map[soft->proto]; 1104 1101 1105 1102 if (oldp != newp) { 1106 1103 arc_printk(D_PROTO, dev, 1107 1104 "got protocol %02Xh; encap for host %02Xh is now '%c' (was '%c')\n", 1108 - soft->proto, pkt.hard.source, 1105 + soft->proto, rxdata.pkt.hard.source, 1109 1106 newp->suffix, oldp->suffix); 1110 1107 } 1111 1108 } ··· 1114 1111 lp->default_proto[0] = soft->proto; 1115 1112 1116 1113 /* in striking contrast, the following isn't a hack. */ 1117 - lp->default_proto[pkt.hard.source] = soft->proto; 1114 + lp->default_proto[rxdata.pkt.hard.source] = soft->proto; 1118 1115 } 1119 1116 /* call the protocol-specific receiver. */ 1120 - arc_proto_map[soft->proto]->rx(dev, bufnum, &pkt, length); 1117 + arc_proto_map[soft->proto]->rx(dev, bufnum, &rxdata.pkt, length); 1121 1118 } 1122 1119 1123 1120 static void null_rx(struct net_device *dev, int bufnum,