mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-17 17:53:56 +08:00
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>
This commit is contained in:
parent
0edc3f703f
commit
02a0704683
@ -1063,31 +1063,34 @@ EXPORT_SYMBOL(arcnet_interrupt);
|
||||
static void arcnet_rx(struct net_device *dev, int bufnum)
|
||||
{
|
||||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
struct archdr pkt;
|
||||
union {
|
||||
struct archdr pkt;
|
||||
char buf[512];
|
||||
} rxdata;
|
||||
struct arc_rfc1201 *soft;
|
||||
int length, ofs;
|
||||
|
||||
soft = &pkt.soft.rfc1201;
|
||||
soft = &rxdata.pkt.soft.rfc1201;
|
||||
|
||||
lp->hw.copy_from_card(dev, bufnum, 0, &pkt, ARC_HDR_SIZE);
|
||||
if (pkt.hard.offset[0]) {
|
||||
ofs = pkt.hard.offset[0];
|
||||
lp->hw.copy_from_card(dev, bufnum, 0, &rxdata.pkt, ARC_HDR_SIZE);
|
||||
if (rxdata.pkt.hard.offset[0]) {
|
||||
ofs = rxdata.pkt.hard.offset[0];
|
||||
length = 256 - ofs;
|
||||
} else {
|
||||
ofs = pkt.hard.offset[1];
|
||||
ofs = rxdata.pkt.hard.offset[1];
|
||||
length = 512 - ofs;
|
||||
}
|
||||
|
||||
/* get the full header, if possible */
|
||||
if (sizeof(pkt.soft) <= length) {
|
||||
lp->hw.copy_from_card(dev, bufnum, ofs, soft, sizeof(pkt.soft));
|
||||
if (sizeof(rxdata.pkt.soft) <= length) {
|
||||
lp->hw.copy_from_card(dev, bufnum, ofs, soft, sizeof(rxdata.pkt.soft));
|
||||
} else {
|
||||
memset(&pkt.soft, 0, sizeof(pkt.soft));
|
||||
memset(&rxdata.pkt.soft, 0, sizeof(rxdata.pkt.soft));
|
||||
lp->hw.copy_from_card(dev, bufnum, ofs, soft, length);
|
||||
}
|
||||
|
||||
arc_printk(D_DURING, dev, "Buffer #%d: received packet from %02Xh to %02Xh (%d+4 bytes)\n",
|
||||
bufnum, pkt.hard.source, pkt.hard.dest, length);
|
||||
bufnum, rxdata.pkt.hard.source, rxdata.pkt.hard.dest, length);
|
||||
|
||||
dev->stats.rx_packets++;
|
||||
dev->stats.rx_bytes += length + ARC_HDR_SIZE;
|
||||
@ -1096,13 +1099,13 @@ static void arcnet_rx(struct net_device *dev, int bufnum)
|
||||
if (arc_proto_map[soft->proto]->is_ip) {
|
||||
if (BUGLVL(D_PROTO)) {
|
||||
struct ArcProto
|
||||
*oldp = arc_proto_map[lp->default_proto[pkt.hard.source]],
|
||||
*oldp = arc_proto_map[lp->default_proto[rxdata.pkt.hard.source]],
|
||||
*newp = arc_proto_map[soft->proto];
|
||||
|
||||
if (oldp != newp) {
|
||||
arc_printk(D_PROTO, dev,
|
||||
"got protocol %02Xh; encap for host %02Xh is now '%c' (was '%c')\n",
|
||||
soft->proto, pkt.hard.source,
|
||||
soft->proto, rxdata.pkt.hard.source,
|
||||
newp->suffix, oldp->suffix);
|
||||
}
|
||||
}
|
||||
@ -1111,10 +1114,10 @@ static void arcnet_rx(struct net_device *dev, int bufnum)
|
||||
lp->default_proto[0] = soft->proto;
|
||||
|
||||
/* in striking contrast, the following isn't a hack. */
|
||||
lp->default_proto[pkt.hard.source] = soft->proto;
|
||||
lp->default_proto[rxdata.pkt.hard.source] = soft->proto;
|
||||
}
|
||||
/* call the protocol-specific receiver. */
|
||||
arc_proto_map[soft->proto]->rx(dev, bufnum, &pkt, length);
|
||||
arc_proto_map[soft->proto]->rx(dev, bufnum, &rxdata.pkt, length);
|
||||
}
|
||||
|
||||
static void null_rx(struct net_device *dev, int bufnum,
|
||||
|
Loading…
Reference in New Issue
Block a user