On Fri, Sep 20, 2019 at 04:08:21PM +0200, Uwe Kleine-König wrote: > 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. > > Cc: stable@xxxxxxxxxxxxxxx # v2.4.0+ > Signed-off-by: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx> Acked-by: Michael Grzeschik <m.grzeschik@xxxxxxxxxxxxxx> > --- > Hello, > > the problem exists in v2.4.0 already, I didn't look further to identify > the offending commit. > > Best regards > Uwe > --- > drivers/net/arcnet/arcnet.c | 31 +++++++++++++++++-------------- > 1 file changed, 17 insertions(+), 14 deletions(-) > > diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c > index 0efef7aa5b89..2b8cf58e4de0 100644 > --- a/drivers/net/arcnet/arcnet.c > +++ b/drivers/net/arcnet/arcnet.c > @@ -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, > -- > 2.23.0 > > -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
Attachment:
signature.asc
Description: PGP signature