aboutsummaryrefslogtreecommitdiff
path: root/linux/dev/drivers
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2021-08-17 00:05:17 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2021-08-17 00:05:17 +0200
commit4a704a0ad95973249544f3f95e30e328e701a871 (patch)
tree861ef383f6de782b5f09c13d2d9d5d65836c03e1 /linux/dev/drivers
parentf67a2a46931028753364ab6bcb6a43c12f8303b2 (diff)
downloadgnumach-4a704a0ad95973249544f3f95e30e328e701a871.tar.gz
gnumach-4a704a0ad95973249544f3f95e30e328e701a871.tar.bz2
gnumach-4a704a0ad95973249544f3f95e30e328e701a871.zip
block: Look out for disk sector number overflow
* linux/dev/drivers/block/ahci.c (ahci_do_port_request): Reject sectors beyond LBA48 or LBA28. * linux/dev/glue/block.c (check_rw_block): New function. (rdwr_partial, rdwr_full): Use check_rw_block to reject block number overflows. * linux/src/drivers/block/ide.c (do_rw_disk): Reject sectors beyond LBA28 or CHS.
Diffstat (limited to 'linux/dev/drivers')
-rw-r--r--linux/dev/drivers/block/ahci.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/linux/dev/drivers/block/ahci.c b/linux/dev/drivers/block/ahci.c
index ce2ac403..b8fd9dae 100644
--- a/linux/dev/drivers/block/ahci.c
+++ b/linux/dev/drivers/block/ahci.c
@@ -288,7 +288,7 @@ static void ahci_end_request(int uptodate)
}
/* Push the request to the controler port */
-static void ahci_do_port_request(struct port *port, unsigned long long sector, struct request *rq)
+static int ahci_do_port_request(struct port *port, unsigned long long sector, struct request *rq)
{
struct ahci_command *command = port->command;
struct ahci_cmd_tbl *prdtl = port->prdtl;
@@ -305,16 +305,25 @@ static void ahci_do_port_request(struct port *port, unsigned long long sector, s
fis_h2d = (void*) &prdtl[slot].cfis;
fis_h2d->fis_type = FIS_TYPE_REG_H2D;
fis_h2d->flags = 128;
- if (port->lba48)
+ if (port->lba48) {
+ if (sector >= 1ULL << 48) {
+ printk("sector %llu beyond LBA48\n", sector);
+ return -EOVERFLOW;
+ }
if (rq->cmd == READ)
fis_h2d->command = WIN_READDMA_EXT;
else
fis_h2d->command = WIN_WRITEDMA_EXT;
- else
+ } else {
+ if (sector >= 1ULL << 28) {
+ printk("sector %llu beyond LBA28\n", sector);
+ return -EOVERFLOW;
+ }
if (rq->cmd == READ)
fis_h2d->command = WIN_READDMA;
else
fis_h2d->command = WIN_WRITEDMA;
+ }
fis_h2d->device = 1<<6; /* LBA */
@@ -353,6 +362,7 @@ static void ahci_do_port_request(struct port *port, unsigned long long sector, s
writel(1 << slot, &port->ahci_port->ci);
/* TODO: IRQ timeout handler */
+ return 0;
}
/* Called by block core to push a request */
@@ -409,7 +419,8 @@ static void ahci_do_request() /* invoked with cli() */
}
/* Push this to the port */
- ahci_do_port_request(port, block, rq);
+ if (ahci_do_port_request(port, block, rq))
+ goto kill_rq;
return;
kill_rq: