Revision 924a9bc362a5223cd448ca08c3dde21235adc310 authored by Balazs Nemeth on 09 March 2021, 11:31:00 UTC, committed by David S. Miller on 10 March 2021, 00:12:20 UTC
For gso packets, virtio_net_hdr_set_proto sets the protocol (if it isn't
set) based on the type in the virtio net hdr, but the skb could contain
anything since it could come from packet_snd through a raw socket. If
there is a mismatch between what virtio_net_hdr_set_proto sets and
the actual protocol, then the skb could be handled incorrectly later
on.

An example where this poses an issue is with the subsequent call to
skb_flow_dissect_flow_keys_basic which relies on skb->protocol being set
correctly. A specially crafted packet could fool
skb_flow_dissect_flow_keys_basic preventing EINVAL to be returned.

Avoid blindly trusting the information provided by the virtio net header
by checking that the protocol in the packet actually matches the
protocol set by virtio_net_hdr_set_proto. Note that since the protocol
is only checked if skb->dev implements header_ops->parse_protocol,
packets from devices without the implementation are not checked at this
stage.

Fixes: 9274124f023b ("net: stricter validation of untrusted gso packets")
Signed-off-by: Balazs Nemeth <bnemeth@redhat.com>
Acked-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 286a862
Raw File
triflex.c
// SPDX-License-Identifier: GPL-2.0-only
/*
 * IDE Chipset driver for the Compaq TriFlex IDE controller.
 * 
 * Known to work with the Compaq Workstation 5x00 series.
 *
 * Copyright (C) 2002 Hewlett-Packard Development Group, L.P.
 * Author: Torben Mathiasen <torben.mathiasen@hp.com>
 * 
 * Loosely based on the piix & svwks drivers.
 *
 * Documentation:
 *	Not publicly available.
 */

#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/init.h>

#define DRV_NAME "triflex"

static void triflex_set_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
	struct pci_dev *dev = to_pci_dev(hwif->dev);
	u32 triflex_timings = 0;
	u16 timing = 0;
	u8 channel_offset = hwif->channel ? 0x74 : 0x70, unit = drive->dn & 1;

	pci_read_config_dword(dev, channel_offset, &triflex_timings);

	switch (drive->dma_mode) {
		case XFER_MW_DMA_2:
			timing = 0x0103; 
			break;
		case XFER_MW_DMA_1:
			timing = 0x0203;
			break;
		case XFER_MW_DMA_0:
			timing = 0x0808;
			break;
		case XFER_SW_DMA_2:
		case XFER_SW_DMA_1:
		case XFER_SW_DMA_0:
			timing = 0x0f0f;
			break;
		case XFER_PIO_4:
			timing = 0x0202;
			break;
		case XFER_PIO_3:
			timing = 0x0204;
			break;
		case XFER_PIO_2:
			timing = 0x0404;
			break;
		case XFER_PIO_1:
			timing = 0x0508;
			break;
		case XFER_PIO_0:
			timing = 0x0808;
			break;
	}

	triflex_timings &= ~(0xFFFF << (16 * unit));
	triflex_timings |= (timing << (16 * unit));
	
	pci_write_config_dword(dev, channel_offset, triflex_timings);
}

static void triflex_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
	drive->dma_mode = drive->pio_mode;
	triflex_set_mode(hwif, drive);
}

static const struct ide_port_ops triflex_port_ops = {
	.set_pio_mode		= triflex_set_pio_mode,
	.set_dma_mode		= triflex_set_mode,
};

static const struct ide_port_info triflex_device = {
	.name		= DRV_NAME,
	.enablebits	= {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
	.port_ops	= &triflex_port_ops,
	.pio_mask	= ATA_PIO4,
	.swdma_mask	= ATA_SWDMA2,
	.mwdma_mask	= ATA_MWDMA2,
};

static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
	return ide_pci_init_one(dev, &triflex_device, NULL);
}

static const struct pci_device_id triflex_pci_tbl[] = {
	{ PCI_VDEVICE(COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE), 0 },
	{ 0, },
};
MODULE_DEVICE_TABLE(pci, triflex_pci_tbl);

#ifdef CONFIG_PM
static int triflex_ide_pci_suspend(struct pci_dev *dev, pm_message_t state)
{
	/*
	 * We must not disable or powerdown the device.
	 * APM bios refuses to suspend if IDE is not accessible.
	 */
	pci_save_state(dev);
	return 0;
}
#else
#define triflex_ide_pci_suspend NULL
#endif

static struct pci_driver triflex_pci_driver = {
	.name		= "TRIFLEX_IDE",
	.id_table	= triflex_pci_tbl,
	.probe		= triflex_init_one,
	.remove		= ide_pci_remove,
	.suspend	= triflex_ide_pci_suspend,
	.resume		= ide_pci_resume,
};

static int __init triflex_ide_init(void)
{
	return ide_pci_register_driver(&triflex_pci_driver);
}

static void __exit triflex_ide_exit(void)
{
	pci_unregister_driver(&triflex_pci_driver);
}

module_init(triflex_ide_init);
module_exit(triflex_ide_exit);

MODULE_AUTHOR("Torben Mathiasen");
MODULE_DESCRIPTION("PCI driver module for Compaq Triflex IDE");
MODULE_LICENSE("GPL");


back to top