summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2017-11-01 01:20:50 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2017-11-01 01:26:48 +0100
commit4282cb6241f47f9db9071814c284fd8a704b3cf3 (patch)
treeb0c26c4f8fd39406c3bd85293bccb9b1074051ae
parent0e91d138a30a85eedceb3dbfd28b478a83232979 (diff)
linux block: fix outbound access to non-directmap user data
* linux/dev/glue/block.c (rdwr_full): Set BH_Bounce if the physical address of the user data is not in directmap.
-rw-r--r--linux/dev/glue/block.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/linux/dev/glue/block.c b/linux/dev/glue/block.c
index a8fa9153..0a5b1c87 100644
--- a/linux/dev/glue/block.c
+++ b/linux/dev/glue/block.c
@@ -578,6 +578,7 @@ rdwr_full (int rw, kdev_t dev, loff_t *off, char **buf, int *resid, int bshift)
int cc, err = 0, i, j, nb, nbuf;
long blk;
struct buffer_head bhead[MAX_BUF], *bh, *bhp[MAX_BUF];
+ phys_addr_t pa;
assert ((*off & BMASK) == 0);
@@ -592,7 +593,10 @@ rdwr_full (int rw, kdev_t dev, loff_t *off, char **buf, int *resid, int bshift)
if (rw == WRITE)
set_bit (BH_Dirty, &bh->b_state);
cc = PAGE_SIZE - (((int) *buf + (nb << bshift)) & PAGE_MASK);
- if (cc >= BSIZE && (((int) *buf + (nb << bshift)) & 511) == 0)
+ pa = pmap_extract (vm_map_pmap (device_io_map),
+ (((vm_offset_t) *buf) + (nb << bshift)));
+ if (cc >= BSIZE && (((int) *buf + (nb << bshift)) & 511) == 0
+ && pa + cc <= VM_PAGE_DIRECTMAP_LIMIT)
cc &= ~BMASK;
else
{
@@ -602,9 +606,7 @@ rdwr_full (int rw, kdev_t dev, loff_t *off, char **buf, int *resid, int bshift)
if (cc > ((nbuf - nb) << bshift))
cc = (nbuf - nb) << bshift;
if (! test_bit (BH_Bounce, &bh->b_state))
- bh->b_data = (char *) phystokv(pmap_extract (vm_map_pmap (device_io_map),
- (((vm_offset_t) *buf)
- + (nb << bshift))));
+ bh->b_data = (char *) phystokv(pa);
else
{
bh->b_data = alloc_buffer (cc);