Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 337da470 authored by Uwe Kleine-König's avatar Uwe Kleine-König Committed by Greg Kroah-Hartman
Browse files

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: 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>
parent d272e49d
Loading
Loading
Loading
Loading
+17 −14
Original line number Diff line number Diff line
@@ -1009,31 +1009,34 @@ EXPORT_SYMBOL(arcnet_interrupt);
static void arcnet_rx(struct net_device *dev, int bufnum)
{
	struct arcnet_local *lp = netdev_priv(dev);
	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;
@@ -1042,13 +1045,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);
			}
		}
@@ -1057,10 +1060,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,