Skip to content

Commit 86624ba

Browse files
jgunthorpeawilliam
authored andcommitted
vfio/pci: Do vf_token checks for VFIO_DEVICE_BIND_IOMMUFD
This was missed during the initial implementation. The VFIO PCI encodes the vf_token inside the device name when opening the device from the group FD, something like: "0000:04:10.0 vf_token=bd8d9d2b-5a5f-4f5a-a211-f591514ba1f3" This is used to control access to a VF unless there is co-ordination with the owner of the PF. Since we no longer have a device name in the cdev path, pass the token directly through VFIO_DEVICE_BIND_IOMMUFD using an optional field indicated by VFIO_DEVICE_BIND_FLAG_TOKEN. Fixes: 5fcc269 ("vfio: Add VFIO_DEVICE_BIND_IOMMUFD") Tested-by: Shameer Kolothum <[email protected]> Reviewed-by: Yi Liu <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alex Williamson <[email protected]>
1 parent b306019 commit 86624ba

File tree

12 files changed

+76
-12
lines changed

12 files changed

+76
-12
lines changed

drivers/vfio/device_cdev.c

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,22 +60,50 @@ static void vfio_df_get_kvm_safe(struct vfio_device_file *df)
6060
spin_unlock(&df->kvm_ref_lock);
6161
}
6262

63+
static int vfio_df_check_token(struct vfio_device *device,
64+
const struct vfio_device_bind_iommufd *bind)
65+
{
66+
uuid_t uuid;
67+
68+
if (!device->ops->match_token_uuid) {
69+
if (bind->flags & VFIO_DEVICE_BIND_FLAG_TOKEN)
70+
return -EINVAL;
71+
return 0;
72+
}
73+
74+
if (!(bind->flags & VFIO_DEVICE_BIND_FLAG_TOKEN))
75+
return device->ops->match_token_uuid(device, NULL);
76+
77+
if (copy_from_user(&uuid, u64_to_user_ptr(bind->token_uuid_ptr),
78+
sizeof(uuid)))
79+
return -EFAULT;
80+
return device->ops->match_token_uuid(device, &uuid);
81+
}
82+
6383
long vfio_df_ioctl_bind_iommufd(struct vfio_device_file *df,
6484
struct vfio_device_bind_iommufd __user *arg)
6585
{
86+
const u32 VALID_FLAGS = VFIO_DEVICE_BIND_FLAG_TOKEN;
6687
struct vfio_device *device = df->device;
6788
struct vfio_device_bind_iommufd bind;
6889
unsigned long minsz;
90+
u32 user_size;
6991
int ret;
7092

7193
static_assert(__same_type(arg->out_devid, df->devid));
7294

7395
minsz = offsetofend(struct vfio_device_bind_iommufd, out_devid);
7496

75-
if (copy_from_user(&bind, arg, minsz))
76-
return -EFAULT;
97+
ret = get_user(user_size, &arg->argsz);
98+
if (ret)
99+
return ret;
100+
if (user_size < minsz)
101+
return -EINVAL;
102+
ret = copy_struct_from_user(&bind, minsz, arg, user_size);
103+
if (ret)
104+
return ret;
77105

78-
if (bind.argsz < minsz || bind.flags || bind.iommufd < 0)
106+
if (bind.iommufd < 0 || bind.flags & ~VALID_FLAGS)
79107
return -EINVAL;
80108

81109
/* BIND_IOMMUFD only allowed for cdev fds */
@@ -93,6 +121,10 @@ long vfio_df_ioctl_bind_iommufd(struct vfio_device_file *df,
93121
goto out_unlock;
94122
}
95123

124+
ret = vfio_df_check_token(device, &bind);
125+
if (ret)
126+
goto out_unlock;
127+
96128
df->iommufd = iommufd_ctx_from_fd(bind.iommufd);
97129
if (IS_ERR(df->iommufd)) {
98130
ret = PTR_ERR(df->iommufd);

drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,6 +1583,7 @@ static const struct vfio_device_ops hisi_acc_vfio_pci_ops = {
15831583
.mmap = vfio_pci_core_mmap,
15841584
.request = vfio_pci_core_request,
15851585
.match = vfio_pci_core_match,
1586+
.match_token_uuid = vfio_pci_core_match_token_uuid,
15861587
.bind_iommufd = vfio_iommufd_physical_bind,
15871588
.unbind_iommufd = vfio_iommufd_physical_unbind,
15881589
.attach_ioas = vfio_iommufd_physical_attach_ioas,

drivers/vfio/pci/mlx5/main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,6 +1372,7 @@ static const struct vfio_device_ops mlx5vf_pci_ops = {
13721372
.mmap = vfio_pci_core_mmap,
13731373
.request = vfio_pci_core_request,
13741374
.match = vfio_pci_core_match,
1375+
.match_token_uuid = vfio_pci_core_match_token_uuid,
13751376
.bind_iommufd = vfio_iommufd_physical_bind,
13761377
.unbind_iommufd = vfio_iommufd_physical_unbind,
13771378
.attach_ioas = vfio_iommufd_physical_attach_ioas,

drivers/vfio/pci/nvgrace-gpu/main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,7 @@ static const struct vfio_device_ops nvgrace_gpu_pci_ops = {
696696
.mmap = nvgrace_gpu_mmap,
697697
.request = vfio_pci_core_request,
698698
.match = vfio_pci_core_match,
699+
.match_token_uuid = vfio_pci_core_match_token_uuid,
699700
.bind_iommufd = vfio_iommufd_physical_bind,
700701
.unbind_iommufd = vfio_iommufd_physical_unbind,
701702
.attach_ioas = vfio_iommufd_physical_attach_ioas,
@@ -715,6 +716,7 @@ static const struct vfio_device_ops nvgrace_gpu_pci_core_ops = {
715716
.mmap = vfio_pci_core_mmap,
716717
.request = vfio_pci_core_request,
717718
.match = vfio_pci_core_match,
719+
.match_token_uuid = vfio_pci_core_match_token_uuid,
718720
.bind_iommufd = vfio_iommufd_physical_bind,
719721
.unbind_iommufd = vfio_iommufd_physical_unbind,
720722
.attach_ioas = vfio_iommufd_physical_attach_ioas,

drivers/vfio/pci/pds/vfio_dev.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ static const struct vfio_device_ops pds_vfio_ops = {
201201
.mmap = vfio_pci_core_mmap,
202202
.request = vfio_pci_core_request,
203203
.match = vfio_pci_core_match,
204+
.match_token_uuid = vfio_pci_core_match_token_uuid,
204205
.bind_iommufd = vfio_iommufd_physical_bind,
205206
.unbind_iommufd = vfio_iommufd_physical_unbind,
206207
.attach_ioas = vfio_iommufd_physical_attach_ioas,

drivers/vfio/pci/qat/main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,7 @@ static const struct vfio_device_ops qat_vf_pci_ops = {
614614
.mmap = vfio_pci_core_mmap,
615615
.request = vfio_pci_core_request,
616616
.match = vfio_pci_core_match,
617+
.match_token_uuid = vfio_pci_core_match_token_uuid,
617618
.bind_iommufd = vfio_iommufd_physical_bind,
618619
.unbind_iommufd = vfio_iommufd_physical_unbind,
619620
.attach_ioas = vfio_iommufd_physical_attach_ioas,

drivers/vfio/pci/vfio_pci.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ static const struct vfio_device_ops vfio_pci_ops = {
138138
.mmap = vfio_pci_core_mmap,
139139
.request = vfio_pci_core_request,
140140
.match = vfio_pci_core_match,
141+
.match_token_uuid = vfio_pci_core_match_token_uuid,
141142
.bind_iommufd = vfio_iommufd_physical_bind,
142143
.unbind_iommufd = vfio_iommufd_physical_unbind,
143144
.attach_ioas = vfio_iommufd_physical_attach_ioas,

drivers/vfio/pci/vfio_pci_core.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1821,9 +1821,13 @@ void vfio_pci_core_request(struct vfio_device *core_vdev, unsigned int count)
18211821
}
18221822
EXPORT_SYMBOL_GPL(vfio_pci_core_request);
18231823

1824-
static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev,
1825-
bool vf_token, uuid_t *uuid)
1824+
int vfio_pci_core_match_token_uuid(struct vfio_device *core_vdev,
1825+
const uuid_t *uuid)
1826+
18261827
{
1828+
struct vfio_pci_core_device *vdev =
1829+
container_of(core_vdev, struct vfio_pci_core_device, vdev);
1830+
18271831
/*
18281832
* There's always some degree of trust or collaboration between SR-IOV
18291833
* PF and VFs, even if just that the PF hosts the SR-IOV capability and
@@ -1854,15 +1858,15 @@ static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev,
18541858
bool match;
18551859

18561860
if (!pf_vdev) {
1857-
if (!vf_token)
1861+
if (!uuid)
18581862
return 0; /* PF is not vfio-pci, no VF token */
18591863

18601864
pci_info_ratelimited(vdev->pdev,
18611865
"VF token incorrectly provided, PF not bound to vfio-pci\n");
18621866
return -EINVAL;
18631867
}
18641868

1865-
if (!vf_token) {
1869+
if (!uuid) {
18661870
pci_info_ratelimited(vdev->pdev,
18671871
"VF token required to access device\n");
18681872
return -EACCES;
@@ -1880,7 +1884,7 @@ static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev,
18801884
} else if (vdev->vf_token) {
18811885
mutex_lock(&vdev->vf_token->lock);
18821886
if (vdev->vf_token->users) {
1883-
if (!vf_token) {
1887+
if (!uuid) {
18841888
mutex_unlock(&vdev->vf_token->lock);
18851889
pci_info_ratelimited(vdev->pdev,
18861890
"VF token required to access device\n");
@@ -1893,19 +1897,20 @@ static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev,
18931897
"Incorrect VF token provided for device\n");
18941898
return -EACCES;
18951899
}
1896-
} else if (vf_token) {
1900+
} else if (uuid) {
18971901
uuid_copy(&vdev->vf_token->uuid, uuid);
18981902
}
18991903

19001904
mutex_unlock(&vdev->vf_token->lock);
1901-
} else if (vf_token) {
1905+
} else if (uuid) {
19021906
pci_info_ratelimited(vdev->pdev,
19031907
"VF token incorrectly provided, not a PF or VF\n");
19041908
return -EINVAL;
19051909
}
19061910

19071911
return 0;
19081912
}
1913+
EXPORT_SYMBOL_GPL(vfio_pci_core_match_token_uuid);
19091914

19101915
#define VF_TOKEN_ARG "vf_token="
19111916

@@ -1952,7 +1957,8 @@ int vfio_pci_core_match(struct vfio_device *core_vdev, char *buf)
19521957
}
19531958
}
19541959

1955-
ret = vfio_pci_validate_vf_token(vdev, vf_token, &uuid);
1960+
ret = core_vdev->ops->match_token_uuid(core_vdev,
1961+
vf_token ? &uuid : NULL);
19561962
if (ret)
19571963
return ret;
19581964

drivers/vfio/pci/virtio/main.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ static const struct vfio_device_ops virtiovf_vfio_pci_lm_ops = {
9494
.mmap = vfio_pci_core_mmap,
9595
.request = vfio_pci_core_request,
9696
.match = vfio_pci_core_match,
97+
.match_token_uuid = vfio_pci_core_match_token_uuid,
9798
.bind_iommufd = vfio_iommufd_physical_bind,
9899
.unbind_iommufd = vfio_iommufd_physical_unbind,
99100
.attach_ioas = vfio_iommufd_physical_attach_ioas,
@@ -114,6 +115,7 @@ static const struct vfio_device_ops virtiovf_vfio_pci_tran_lm_ops = {
114115
.mmap = vfio_pci_core_mmap,
115116
.request = vfio_pci_core_request,
116117
.match = vfio_pci_core_match,
118+
.match_token_uuid = vfio_pci_core_match_token_uuid,
117119
.bind_iommufd = vfio_iommufd_physical_bind,
118120
.unbind_iommufd = vfio_iommufd_physical_unbind,
119121
.attach_ioas = vfio_iommufd_physical_attach_ioas,
@@ -134,6 +136,7 @@ static const struct vfio_device_ops virtiovf_vfio_pci_ops = {
134136
.mmap = vfio_pci_core_mmap,
135137
.request = vfio_pci_core_request,
136138
.match = vfio_pci_core_match,
139+
.match_token_uuid = vfio_pci_core_match_token_uuid,
137140
.bind_iommufd = vfio_iommufd_physical_bind,
138141
.unbind_iommufd = vfio_iommufd_physical_unbind,
139142
.attach_ioas = vfio_iommufd_physical_attach_ioas,

include/linux/vfio.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ struct vfio_device {
105105
* @match: Optional device name match callback (return: 0 for no-match, >0 for
106106
* match, -errno for abort (ex. match with insufficient or incorrect
107107
* additional args)
108+
* @match_token_uuid: Optional device token match/validation. Return 0
109+
* if the uuid is valid for the device, -errno otherwise. uuid is NULL
110+
* if none was provided.
108111
* @dma_unmap: Called when userspace unmaps IOVA from the container
109112
* this device is attached to.
110113
* @device_feature: Optional, fill in the VFIO_DEVICE_FEATURE ioctl
@@ -132,6 +135,7 @@ struct vfio_device_ops {
132135
int (*mmap)(struct vfio_device *vdev, struct vm_area_struct *vma);
133136
void (*request)(struct vfio_device *vdev, unsigned int count);
134137
int (*match)(struct vfio_device *vdev, char *buf);
138+
int (*match_token_uuid)(struct vfio_device *vdev, const uuid_t *uuid);
135139
void (*dma_unmap)(struct vfio_device *vdev, u64 iova, u64 length);
136140
int (*device_feature)(struct vfio_device *device, u32 flags,
137141
void __user *arg, size_t argsz);

0 commit comments

Comments
 (0)