lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:	Thu, 20 Nov 2014 15:11:23 +0100
From:	Antonios Motakis <a.motakis@...tualopensystems.com>
To:	Eric Auger <eric.auger@...aro.org>
Cc:	kvm-arm <kvmarm@...ts.cs.columbia.edu>,
	Linux IOMMU <iommu@...ts.linux-foundation.org>,
	Alex Williamson <alex.williamson@...hat.com>,
	Will Deacon <will.deacon@....com>,
	VirtualOpenSystems Technical Team <tech@...tualopensystems.com>,
	Christoffer Dall <christoffer.dall@...aro.org>,
	Kim Phillips <kim.phillips@...escale.com>,
	Marc Zyngier <marc.zyngier@....com>,
	"open list:VFIO DRIVER <kvm@...r.kernel.org>, open list" 
	<linux-kernel@...r.kernel.org>
Subject: Re: [PATCH v9 08/19] vfio/platform: read and write support for the
 device fd

On Wed, Nov 12, 2014 at 4:46 PM, Eric Auger <eric.auger@...aro.org> wrote:
> On 10/27/2014 07:07 PM, Antonios Motakis wrote:
>> VFIO returns a file descriptor which we can use to manipulate the memory
>> regions of the device. Usually, the user will mmap memory regions that are
>> addressable on page boundaries, however for memory regions where this is
>> not the case we cannot provide mmap functionality due to security concerns.
>> For this reason we also need allow to read and write to the memory regions
> some rewording needed here
>> via the file descriptor. Implement this funcionality
> typo
>

Ack!

> Regards
>
> Eric
>  only for MMIO regions
>> of platform devices; PIO regions are not being handled at this point.
>>
>> Signed-off-by: Antonios Motakis <a.motakis@...tualopensystems.com>
>> ---
>>  drivers/vfio/platform/vfio_platform_common.c  | 150 ++++++++++++++++++++++++++
>>  drivers/vfio/platform/vfio_platform_private.h |   1 +
>>  2 files changed, 151 insertions(+)
>>
>> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
>> index 82de752..e10a8d0 100644
>> --- a/drivers/vfio/platform/vfio_platform_common.c
>> +++ b/drivers/vfio/platform/vfio_platform_common.c
>> @@ -55,6 +55,10 @@ static int vfio_platform_regions_init(struct vfio_platform_device *vdev)
>>               switch (resource_type(res)) {
>>               case IORESOURCE_MEM:
>>                       vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_MMIO;
>> +                     vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_READ;
>> +                     if (!(res->flags & IORESOURCE_READONLY))
>> +                             vdev->regions[i].flags |=
>> +                                     VFIO_REGION_INFO_FLAG_WRITE;
>>                       break;
>>               case IORESOURCE_IO:
>>                       vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_PIO;
>> @@ -74,6 +78,11 @@ err:
>>
>>  static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
>>  {
>> +     int i;
>> +
>> +     for (i = 0; i < vdev->num_regions; i++)
>> +             iounmap(vdev->regions[i].ioaddr);
>> +
>>       vdev->num_regions = 0;
>>       kfree(vdev->regions);
>>  }
>> @@ -176,15 +185,156 @@ static long vfio_platform_ioctl(void *device_data,
>>       return -ENOTTY;
>>  }
>>
>> +static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg,
>> +                                    char __user *buf, size_t count,
>> +                                    loff_t off)
>> +{
>> +     unsigned int done = 0;
>> +
>> +     if (!reg.ioaddr) {
>> +             reg.ioaddr =
>> +                     ioremap_nocache(reg.addr, reg.size);
>> +
>> +             if (!reg.ioaddr)
>> +                     return -ENOMEM;
>> +     }
>> +
>> +     while (count) {
>> +             size_t filled;
>> +
>> +             if (count >= 4 && !(off % 4)) {
>> +                     u32 val;
>> +
>> +                     val = ioread32(reg.ioaddr + off);
>> +                     if (copy_to_user(buf, &val, 4))
>> +                             goto err;
>> +
>> +                     filled = 4;
>> +             } else if (count >= 2 && !(off % 2)) {
>> +                     u16 val;
>> +
>> +                     val = ioread16(reg.ioaddr + off);
>> +                     if (copy_to_user(buf, &val, 2))
>> +                             goto err;
>> +
>> +                     filled = 2;
>> +             } else {
>> +                     u8 val;
>> +
>> +                     val = ioread8(reg.ioaddr + off);
>> +                     if (copy_to_user(buf, &val, 1))
>> +                             goto err;
>> +
>> +                     filled = 1;
>> +             }
>> +
>> +
>> +             count -= filled;
>> +             done += filled;
>> +             off += filled;
>> +             buf += filled;
>> +     }
>> +
>> +     return done;
>> +err:
>> +     return -EFAULT;
>> +}
>> +
>>  static ssize_t vfio_platform_read(void *device_data, char __user *buf,
>>                                 size_t count, loff_t *ppos)
>>  {
>> +     struct vfio_platform_device *vdev = device_data;
>> +     unsigned int index = VFIO_PLATFORM_OFFSET_TO_INDEX(*ppos);
>> +     loff_t off = *ppos & VFIO_PLATFORM_OFFSET_MASK;
>> +
>> +     if (index >= vdev->num_regions)
>> +             return -EINVAL;
>> +
>> +     if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ))
>> +             return -EINVAL;
>> +
>> +     if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
>> +             return vfio_platform_read_mmio(vdev->regions[index],
>> +                                                     buf, count, off);
>> +     else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
>> +             return -EINVAL; /* not implemented */
>> +
>>       return -EINVAL;
>>  }
>>
>> +static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg,
>> +                                     const char __user *buf, size_t count,
>> +                                     loff_t off)
>> +{
>> +     unsigned int done = 0;
>> +
>> +     if (!reg.ioaddr) {
>> +             reg.ioaddr =
>> +                     ioremap_nocache(reg.addr, reg.size);
>> +
>> +             if (!reg.ioaddr)
>> +                     return -ENOMEM;
>> +     }
>> +
>> +     while (count) {
>> +             size_t filled;
>> +
>> +             if (count >= 4 && !(off % 4)) {
>> +                     u32 val;
>> +
>> +                     if (copy_from_user(&val, buf, 4))
>> +                             goto err;
>> +                     iowrite32(val, reg.ioaddr + off);
>> +
>> +                     filled = 4;
>> +             } else if (count >= 2 && !(off % 2)) {
>> +                     u16 val;
>> +
>> +                     if (copy_from_user(&val, buf, 2))
>> +                             goto err;
>> +                     iowrite16(val, reg.ioaddr + off);
>> +
>> +                     filled = 2;
>> +             } else {
>> +                     u8 val;
>> +
>> +                     if (copy_from_user(&val, buf, 1))
>> +                             goto err;
>> +                     iowrite8(val, reg.ioaddr + off);
>> +
>> +                     filled = 1;
>> +             }
>> +
>> +             count -= filled;
>> +             done += filled;
>> +             off += filled;
>> +             buf += filled;
>> +     }
>> +
>> +     return done;
>> +err:
>> +     return -EFAULT;
>> +}
>> +
>>  static ssize_t vfio_platform_write(void *device_data, const char __user *buf,
>>                                  size_t count, loff_t *ppos)
>>  {
>> +     struct vfio_platform_device *vdev = device_data;
>> +     unsigned int index = VFIO_PLATFORM_OFFSET_TO_INDEX(*ppos);
>> +     loff_t off = *ppos & VFIO_PLATFORM_OFFSET_MASK;
>> +
>> +     if (index >= vdev->num_regions)
>> +             return -EINVAL;
>> +
>> +     if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE))
>> +             return -EINVAL;
>> +
>> +     if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
>> +             return vfio_platform_write_mmio(vdev->regions[index],
>> +                                                     buf, count, off);
>> +     else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
>> +             return -EINVAL; /* not implemented */
>> +
>>       return -EINVAL;
>>  }
>>
>> diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
>> index b24729f..1f251b2 100644
>> --- a/drivers/vfio/platform/vfio_platform_private.h
>> +++ b/drivers/vfio/platform/vfio_platform_private.h
>> @@ -31,6 +31,7 @@ struct vfio_platform_region {
>>       u32                     type;
>>  #define VFIO_PLATFORM_REGION_TYPE_MMIO       1
>>  #define VFIO_PLATFORM_REGION_TYPE_PIO        2
>> +     void __iomem            *ioaddr;
>>  };
>>
>>  struct vfio_platform_device {
>>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ