Commit 5078fa6e authored by Uwe Kleine-König's avatar Uwe Kleine-König Committed by Khalid Elmously

arcnet: provide a buffer big enough to actually receive packets

BugLink: https://bugs.launchpad.net/bugs/1848589

[ 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: default avatarUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Acked-by: default avatarMichael Grzeschik <m.grzeschik@pengutronix.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarConnor Kuehl <connor.kuehl@canonical.com>
Signed-off-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
parent 5b696340
...@@ -1009,31 +1009,34 @@ EXPORT_SYMBOL(arcnet_interrupt); ...@@ -1009,31 +1009,34 @@ EXPORT_SYMBOL(arcnet_interrupt);
static void arcnet_rx(struct net_device *dev, int bufnum) static void arcnet_rx(struct net_device *dev, int bufnum)
{ {
struct arcnet_local *lp = netdev_priv(dev); struct arcnet_local *lp = netdev_priv(dev);
struct archdr pkt; union {
struct archdr pkt;
char buf[512];
} rxdata;
struct arc_rfc1201 *soft; struct arc_rfc1201 *soft;
int length, ofs; int length, ofs;
soft = &pkt.soft.rfc1201; soft = &rxdata.pkt.soft.rfc1201;
lp->hw.copy_from_card(dev, bufnum, 0, &pkt, ARC_HDR_SIZE); lp->hw.copy_from_card(dev, bufnum, 0, &rxdata.pkt, ARC_HDR_SIZE);
if (pkt.hard.offset[0]) { if (rxdata.pkt.hard.offset[0]) {
ofs = pkt.hard.offset[0]; ofs = rxdata.pkt.hard.offset[0];
length = 256 - ofs; length = 256 - ofs;
} else { } else {
ofs = pkt.hard.offset[1]; ofs = rxdata.pkt.hard.offset[1];
length = 512 - ofs; length = 512 - ofs;
} }
/* get the full header, if possible */ /* get the full header, if possible */
if (sizeof(pkt.soft) <= length) { if (sizeof(rxdata.pkt.soft) <= length) {
lp->hw.copy_from_card(dev, bufnum, ofs, soft, sizeof(pkt.soft)); lp->hw.copy_from_card(dev, bufnum, ofs, soft, sizeof(rxdata.pkt.soft));
} else { } 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); 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", 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_packets++;
dev->stats.rx_bytes += length + ARC_HDR_SIZE; dev->stats.rx_bytes += length + ARC_HDR_SIZE;
...@@ -1042,13 +1045,13 @@ static void arcnet_rx(struct net_device *dev, int bufnum) ...@@ -1042,13 +1045,13 @@ static void arcnet_rx(struct net_device *dev, int bufnum)
if (arc_proto_map[soft->proto]->is_ip) { if (arc_proto_map[soft->proto]->is_ip) {
if (BUGLVL(D_PROTO)) { if (BUGLVL(D_PROTO)) {
struct ArcProto 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]; *newp = arc_proto_map[soft->proto];
if (oldp != newp) { if (oldp != newp) {
arc_printk(D_PROTO, dev, arc_printk(D_PROTO, dev,
"got protocol %02Xh; encap for host %02Xh is now '%c' (was '%c')\n", "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); newp->suffix, oldp->suffix);
} }
} }
...@@ -1057,10 +1060,10 @@ static void arcnet_rx(struct net_device *dev, int bufnum) ...@@ -1057,10 +1060,10 @@ static void arcnet_rx(struct net_device *dev, int bufnum)
lp->default_proto[0] = soft->proto; lp->default_proto[0] = soft->proto;
/* in striking contrast, the following isn't a hack. */ /* 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. */ /* 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, static void null_rx(struct net_device *dev, int bufnum,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment