]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
vduse: avoid adding implicit padding
authorArnd Bergmann <arnd@arndb.de>
Mon, 2 Feb 2026 22:48:07 +0000 (23:48 +0100)
committerMichael S. Tsirkin <mst@redhat.com>
Mon, 9 Feb 2026 17:21:32 +0000 (12:21 -0500)
The vduse_iova_range_v2 and vduse_iotlb_entry_v2 structures are both
defined in a way that adds implicit padding and is incompatible between
i386 and x86_64 userspace because of the different structure alignment
requirements. Building the header with -Wpadded shows these new warnings:

vduse.h:305:1: error: padding struct size to alignment boundary with 4 bytes [-Werror=padded]
vduse.h:374:1: error: padding struct size to alignment boundary with 4 bytes [-Werror=padded]

Change the amount of padding in these two structures to align them to
64 bit words and avoid those problems. Since the v1 vduse_iotlb_entry
already has an inconsistent size, do not attempt to reuse the structure
but rather list the members indiviudally, with a fixed amount of
padding.

Fixes: 079212f6877e ("vduse: add vq group asid support")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260202224835.559538-1-arnd@kernel.org>

drivers/vdpa/vdpa_user/vduse_dev.c
include/uapi/linux/vduse.h

index 73d1d517dc6c6b576e93e166eb3b9fa65a57afcd..405d59610f76e5dcc6a3fa994ba26f554f17a74f 100644 (file)
@@ -1301,7 +1301,7 @@ static int vduse_dev_iotlb_entry(struct vduse_dev *dev,
        int r = -EINVAL;
        struct vhost_iotlb_map *map;
 
-       if (entry->v1.start > entry->v1.last || entry->asid >= dev->nas)
+       if (entry->start > entry->last || entry->asid >= dev->nas)
                return -EINVAL;
 
        asid = array_index_nospec(entry->asid, dev->nas);
@@ -1312,18 +1312,18 @@ static int vduse_dev_iotlb_entry(struct vduse_dev *dev,
 
        spin_lock(&dev->as[asid].domain->iotlb_lock);
        map = vhost_iotlb_itree_first(dev->as[asid].domain->iotlb,
-                                     entry->v1.start, entry->v1.last);
+                                     entry->start, entry->last);
        if (map) {
                if (f) {
                        const struct vdpa_map_file *map_file;
 
                        map_file = (struct vdpa_map_file *)map->opaque;
-                       entry->v1.offset = map_file->offset;
+                       entry->offset = map_file->offset;
                        *f = get_file(map_file->file);
                }
-               entry->v1.start = map->start;
-               entry->v1.last = map->last;
-               entry->v1.perm = map->perm;
+               entry->start = map->start;
+               entry->last = map->last;
+               entry->perm = map->perm;
                if (capability) {
                        *capability = 0;
 
@@ -1363,14 +1363,8 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd,
                        break;
 
                ret = -EFAULT;
-               if (cmd == VDUSE_IOTLB_GET_FD2) {
-                       if (copy_from_user(&entry, argp, sizeof(entry)))
-                               break;
-               } else {
-                       if (copy_from_user(&entry.v1, argp,
-                                          sizeof(entry.v1)))
-                               break;
-               }
+               if (copy_from_user(&entry, argp, _IOC_SIZE(cmd)))
+                       break;
 
                ret = -EINVAL;
                if (!is_mem_zero((const char *)entry.reserved,
@@ -1385,19 +1379,13 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd,
                if (!f)
                        break;
 
-               if (cmd == VDUSE_IOTLB_GET_FD2)
-                       ret = copy_to_user(argp, &entry,
-                                          sizeof(entry));
-               else
-                       ret = copy_to_user(argp, &entry.v1,
-                                          sizeof(entry.v1));
-
+               ret = copy_to_user(argp, &entry, _IOC_SIZE(cmd));
                if (ret) {
                        ret = -EFAULT;
                        fput(f);
                        break;
                }
-               ret = receive_fd(f, NULL, perm_to_file_flags(entry.v1.perm));
+               ret = receive_fd(f, NULL, perm_to_file_flags(entry.perm));
                fput(f);
                break;
        }
@@ -1603,16 +1591,16 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd,
                } else if (info.asid >= dev->nas)
                        break;
 
-               entry.v1.start = info.start;
-               entry.v1.last = info.last;
+               entry.start = info.start;
+               entry.last = info.last;
                entry.asid = info.asid;
                ret = vduse_dev_iotlb_entry(dev, &entry, NULL,
                                            &info.capability);
                if (ret < 0)
                        break;
 
-               info.start = entry.v1.start;
-               info.last = entry.v1.last;
+               info.start = entry.start;
+               info.last = entry.last;
                info.asid = entry.asid;
 
                ret = -EFAULT;
index 68b4287f9facb2aa1b915c23d8847397837f89e5..361eea511c21827da6bc9eab46e9e62da0833661 100644 (file)
@@ -293,9 +293,13 @@ struct vduse_iova_info {
  * Structure used by VDUSE_IOTLB_GET_FD2 ioctl to find an overlapped IOVA region.
  */
 struct vduse_iotlb_entry_v2 {
-       struct vduse_iotlb_entry v1;
+       __u64 offset;
+       __u64 start;
+       __u64 last;
+       __u8 perm;
+       __u8 padding[7];
        __u32 asid;
-       __u32 reserved[12];
+       __u32 reserved[11];
 };
 
 /*
@@ -365,6 +369,7 @@ struct vduse_iova_range_v2 {
        __u64 start;
        __u64 last;
        __u32 asid;
+       __u32 padding;
 };
 
 /**