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

Commit 0bf79588 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 555161ee
Loading
Loading
Loading
Loading
+17 −14
Original line number Original line Diff line number Diff line
@@ -1063,31 +1063,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);
	union {
		struct archdr pkt;
		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;
@@ -1096,13 +1099,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);
			}
			}
		}
		}
@@ -1111,10 +1114,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,