arcnet: provide a buffer big enough to actually receive packets
[ Upstream commit 108639aac35eb57f1d0e8333f5fc8c7ff68df938 ] 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
555161ee1b
commit
0bf7958858
1 changed files with 17 additions and 14 deletions
|
@ -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…
Add table
Reference in a new issue