Message ID | 20230401151833.124749-11-yi.l.liu@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add vfio_device cdev for iommufd support | expand |
Hi Yi, On 4/1/23 17:18, Yi Liu wrote: > VFIO group has historically allowed multi-open of the device FD. This > was made secure because the "open" was executed via an ioctl to the > group FD which is itself only single open. > > However, no known use of multiple device FDs today. It is kind of a > strange thing to do because new device FDs can naturally be created > via dup(). > > When we implement the new device uAPI (only used in cdev path) there is > no natural way to allow the device itself from being multi-opened in a > secure manner. Without the group FD we cannot prove the security context > of the opener. > > Thus, when moving to the new uAPI we block the ability of opening > a device multiple times. Given old group path still allows it we store > a vfio_group pointer in struct vfio_device_file to differentiate. > > Reviewed-by: Kevin Tian <kevin.tian@intel.com> > Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> > Tested-by: Terrence Xu <terrence.xu@intel.com> > Tested-by: Nicolin Chen <nicolinc@nvidia.com> > Tested-by: Yanting Jiang <yanting.jiang@intel.com> > Signed-off-by: Yi Liu <yi.l.liu@intel.com> Reviewed-by: Eric Auger <eric.auger@redhat.com> Thanks Eric > --- > drivers/vfio/group.c | 2 ++ > drivers/vfio/vfio.h | 2 ++ > drivers/vfio/vfio_main.c | 7 +++++++ > 3 files changed, 11 insertions(+) > > diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c > index d55ce3ca44b7..1af4b9e012a7 100644 > --- a/drivers/vfio/group.c > +++ b/drivers/vfio/group.c > @@ -245,6 +245,8 @@ static struct file *vfio_device_open_file(struct vfio_device *device) > goto err_out; > } > > + df->group = device->group; > + > ret = vfio_device_group_open(df); > if (ret) > goto err_free; > diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h > index b2f20b78a707..f1a448f9d067 100644 > --- a/drivers/vfio/vfio.h > +++ b/drivers/vfio/vfio.h > @@ -18,6 +18,8 @@ struct vfio_container; > > struct vfio_device_file { > struct vfio_device *device; > + struct vfio_group *group; > + > bool access_granted; > spinlock_t kvm_ref_lock; /* protect kvm field */ > struct kvm *kvm; > diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c > index 6d5d3c2180c8..c8721d5d05fa 100644 > --- a/drivers/vfio/vfio_main.c > +++ b/drivers/vfio/vfio_main.c > @@ -477,6 +477,13 @@ int vfio_device_open(struct vfio_device_file *df) > > lockdep_assert_held(&device->dev_set->lock); > > + /* > + * Only the group path allows the device opened multiple times. > + * The device cdev path doesn't have a secure way for it. > + */ > + if (device->open_count != 0 && !df->group) > + return -EINVAL; > + > device->open_count++; > if (device->open_count == 1) { > ret = vfio_device_first_open(df);
Hi Yi, On 4/1/23 17:18, Yi Liu wrote: > VFIO group has historically allowed multi-open of the device FD. This > was made secure because the "open" was executed via an ioctl to the > group FD which is itself only single open. > > However, no known use of multiple device FDs today. It is kind of a > strange thing to do because new device FDs can naturally be created > via dup(). > > When we implement the new device uAPI (only used in cdev path) there is > no natural way to allow the device itself from being multi-opened in a > secure manner. Without the group FD we cannot prove the security context > of the opener. > > Thus, when moving to the new uAPI we block the ability of opening > a device multiple times. Given old group path still allows it we store > a vfio_group pointer in struct vfio_device_file to differentiate. > > Reviewed-by: Kevin Tian <kevin.tian@intel.com> > Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> > Tested-by: Terrence Xu <terrence.xu@intel.com> > Tested-by: Nicolin Chen <nicolinc@nvidia.com> > Tested-by: Yanting Jiang <yanting.jiang@intel.com> > Signed-off-by: Yi Liu <yi.l.liu@intel.com> > --- > drivers/vfio/group.c | 2 ++ > drivers/vfio/vfio.h | 2 ++ > drivers/vfio/vfio_main.c | 7 +++++++ > 3 files changed, 11 insertions(+) > > diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c > index d55ce3ca44b7..1af4b9e012a7 100644 > --- a/drivers/vfio/group.c > +++ b/drivers/vfio/group.c > @@ -245,6 +245,8 @@ static struct file *vfio_device_open_file(struct vfio_device *device) > goto err_out; > } > > + df->group = device->group; > + in previous patches df fields were protected with various locks. I refer to vfio_device_group_open() implementation. No need here? By the way since the group is set here, wrt [PATCH v9 06/25] kvm/vfio: Accept vfio device file from userspace you have a way to determine if a device was opened in the legacy way, no? > ret = vfio_device_group_open(df); > if (ret) > goto err_free; > diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h > index b2f20b78a707..f1a448f9d067 100644 > --- a/drivers/vfio/vfio.h > +++ b/drivers/vfio/vfio.h > @@ -18,6 +18,8 @@ struct vfio_container; > > struct vfio_device_file { > struct vfio_device *device; > + struct vfio_group *group; > + > bool access_granted; > spinlock_t kvm_ref_lock; /* protect kvm field */ > struct kvm *kvm; > diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c > index 6d5d3c2180c8..c8721d5d05fa 100644 > --- a/drivers/vfio/vfio_main.c > +++ b/drivers/vfio/vfio_main.c > @@ -477,6 +477,13 @@ int vfio_device_open(struct vfio_device_file *df) > > lockdep_assert_held(&device->dev_set->lock); > > + /* > + * Only the group path allows the device opened multiple times. allows the device to be opened multiple times > + * The device cdev path doesn't have a secure way for it. > + */ > + if (device->open_count != 0 && !df->group) > + return -EINVAL; > + > device->open_count++; > if (device->open_count == 1) { > ret = vfio_device_first_open(df); Thanks Eric
Hi Eric, > From: Eric Auger <eric.auger@redhat.com> > Sent: Friday, April 7, 2023 5:48 PM > > Hi Yi, > > On 4/1/23 17:18, Yi Liu wrote: > > VFIO group has historically allowed multi-open of the device FD. This > > was made secure because the "open" was executed via an ioctl to the > > group FD which is itself only single open. > > > > However, no known use of multiple device FDs today. It is kind of a > > strange thing to do because new device FDs can naturally be created > > via dup(). > > > > When we implement the new device uAPI (only used in cdev path) there is > > no natural way to allow the device itself from being multi-opened in a > > secure manner. Without the group FD we cannot prove the security context > > of the opener. > > > > Thus, when moving to the new uAPI we block the ability of opening > > a device multiple times. Given old group path still allows it we store > > a vfio_group pointer in struct vfio_device_file to differentiate. > > > > Reviewed-by: Kevin Tian <kevin.tian@intel.com> > > Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> > > Tested-by: Terrence Xu <terrence.xu@intel.com> > > Tested-by: Nicolin Chen <nicolinc@nvidia.com> > > Tested-by: Yanting Jiang <yanting.jiang@intel.com> > > Signed-off-by: Yi Liu <yi.l.liu@intel.com> > > --- > > drivers/vfio/group.c | 2 ++ > > drivers/vfio/vfio.h | 2 ++ > > drivers/vfio/vfio_main.c | 7 +++++++ > > 3 files changed, 11 insertions(+) > > > > diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c > > index d55ce3ca44b7..1af4b9e012a7 100644 > > --- a/drivers/vfio/group.c > > +++ b/drivers/vfio/group.c > > @@ -245,6 +245,8 @@ static struct file *vfio_device_open_file(struct vfio_device > *device) > > goto err_out; > > } > > > > + df->group = device->group; > > + > in previous patches df fields were protected with various locks. I refer > to vfio_device_group_open() implementation. No need here? yes, no need for group. It should be static in the lifecircle of df. > > By the way since the group is set here, wrt [PATCH v9 06/25] kvm/vfio: > Accept vfio device file from userspace you have a way to determine if a > device was opened in the legacy way, no? yes, by this we can tell if a device file is opened by legacy or cdev. But I guess the problem in patch 06/25 is we need to know if the order between set_kvm and open_device is needed. is it? that order requirement is due to that the kvm pointer is needed by open_device() callback. e.g. kvmgt. For other vfio users, this order is not needed or even the KVM_DEV_VFIO_FILE is not needed if vfio is not used to do device passthrough. > > ret = vfio_device_group_open(df); > > if (ret) > > goto err_free; > > diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h > > index b2f20b78a707..f1a448f9d067 100644 > > --- a/drivers/vfio/vfio.h > > +++ b/drivers/vfio/vfio.h > > @@ -18,6 +18,8 @@ struct vfio_container; > > > > struct vfio_device_file { > > struct vfio_device *device; > > + struct vfio_group *group; > > + > > bool access_granted; > > spinlock_t kvm_ref_lock; /* protect kvm field */ > > struct kvm *kvm; > > diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c > > index 6d5d3c2180c8..c8721d5d05fa 100644 > > --- a/drivers/vfio/vfio_main.c > > +++ b/drivers/vfio/vfio_main.c > > @@ -477,6 +477,13 @@ int vfio_device_open(struct vfio_device_file *df) > > > > lockdep_assert_held(&device->dev_set->lock); > > > > + /* > > + * Only the group path allows the device opened multiple times. > allows the device to be opened multiple times got it. Thanks, Yi Liu > > + * The device cdev path doesn't have a secure way for it. > > + */ > > + if (device->open_count != 0 && !df->group) > > + return -EINVAL; > > + > > device->open_count++; > > if (device->open_count == 1) { > > ret = vfio_device_first_open(df); > Thanks > > Eric
diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c index d55ce3ca44b7..1af4b9e012a7 100644 --- a/drivers/vfio/group.c +++ b/drivers/vfio/group.c @@ -245,6 +245,8 @@ static struct file *vfio_device_open_file(struct vfio_device *device) goto err_out; } + df->group = device->group; + ret = vfio_device_group_open(df); if (ret) goto err_free; diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h index b2f20b78a707..f1a448f9d067 100644 --- a/drivers/vfio/vfio.h +++ b/drivers/vfio/vfio.h @@ -18,6 +18,8 @@ struct vfio_container; struct vfio_device_file { struct vfio_device *device; + struct vfio_group *group; + bool access_granted; spinlock_t kvm_ref_lock; /* protect kvm field */ struct kvm *kvm; diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c index 6d5d3c2180c8..c8721d5d05fa 100644 --- a/drivers/vfio/vfio_main.c +++ b/drivers/vfio/vfio_main.c @@ -477,6 +477,13 @@ int vfio_device_open(struct vfio_device_file *df) lockdep_assert_held(&device->dev_set->lock); + /* + * Only the group path allows the device opened multiple times. + * The device cdev path doesn't have a secure way for it. + */ + if (device->open_count != 0 && !df->group) + return -EINVAL; + device->open_count++; if (device->open_count == 1) { ret = vfio_device_first_open(df);