From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
To: "Julian Orth" <ju.orth@gmail.com>,
"Michel Dänzer" <michel.daenzer@mailbox.org>
Cc: "Christian König" <christian.koenig@amd.com>,
"Maxime Ripard" <mripard@kernel.org>,
"Thomas Zimmermann" <tzimmermann@suse.de>,
"David Airlie" <airlied@gmail.com>,
"Simona Vetter" <simona@ffwll.ch>,
"Dmitry Osipenko" <dmitry.osipenko@collabora.com>,
"Rob Clark" <robin.clark@oss.qualcomm.com>,
dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] drm/syncobj: Fix handle <-> fd ioctls with dirty stack
Date: Tue, 3 Mar 2026 17:40:43 +0100 [thread overview]
Message-ID: <bc3417d9-d191-4cc7-95e0-968b0b9bec05@linux.intel.com> (raw)
In-Reply-To: <CAHijbEXkn3+E_u1+aZgLT+pQ_vLYvKKv9VU_5kOuEaFheLRQeg@mail.gmail.com>
Hey,
Den 2026-03-03 kl. 16:36, skrev Julian Orth:
> On Tue, Mar 3, 2026 at 4:29 PM Michel Dänzer <michel.daenzer@mailbox.org> wrote:
>>
>> On 3/3/26 15:59, Christian König wrote:
>>> On 3/3/26 15:53, Maarten Lankhorst wrote:
>>>> Hey,
>>>>
>>>> Den 2026-03-01 kl. 13:34, skrev Julian Orth:
>>>>> Consider the following application:
>>>>>
>>>>> #include <fcntl.h>
>>>>> #include <string.h>
>>>>> #include <drm/drm.h>
>>>>> #include <sys/ioctl.h>
>>>>>
>>>>> int main(void) {
>>>>> int fd = open("/dev/dri/renderD128", O_RDWR);
>>>>> struct drm_syncobj_create arg1;
>>>>> ioctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &arg1);
>>>>> struct drm_syncobj_handle arg2;
>>>>> memset(&arg2, 1, sizeof(arg2)); // simulate dirty stack
>>>>> arg2.handle = arg1.handle;
>>>>> arg2.flags = 0;
>>>>> arg2.fd = 0;
>>>>> arg2.pad = 0;
>>>>> // arg2.point = 0; // userspace is required to set point to 0
>>>>> ioctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &arg2);
>>>>> }
>>>>>
>>>>> The last ioctl returns EINVAL because args->point is not 0. However,
>>>>> userspace developed against older kernel versions is not aware of the
>>>>> new point field and might therefore not initialize it.
>>>>>
>>>>> The correct check would be
>>>>>
>>>>> if (args->flags & DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE)
>>>>> return -EINVAL;
>>>>>
>>>>> However, there might already be userspace that relies on this not
>>>>> returning an error as long as point == 0. Therefore use the more lenient
>>>>> check.
>>>>>
>>>>> Fixes: c2d3a7300695 ("drm/syncobj: Extend EXPORT_SYNC_FILE for timeline syncobjs")
>>>>> Signed-off-by: Julian Orth <ju.orth@gmail.com>
>>>>
>>>> I'm not convinced this is the correct fix.
>>>> Userspace built before the change had the old size for drm_syncobj_create,
>>>> the size is encoded into the ioctl, and zero extended as needed.
>>>>
>>>> See drivers/gpu/drm/drm_ioctl.c:
>>>> out_size = in_size = _IOC_SIZE(cmd);
>>>> ...
>>>> if (ksize > in_size)
>>>> memset(kdata + in_size, 0, ksize - in_size);
>>>>
>>>> This is a bug in a newly built app, and should be handled by explicitly zeroing
>>>> the entire struct or using named initializers, and only setting specific members
>>>> as required.
>>>>
>>>> In particular, apps built before the change will never encounter this bug.
>>>
>>> Yeah, I've realized that after pushing the patch as well.
>>>
>>> But I still think this patch is the right thing to do, because without requesting the functionality by setting the flag the point should clearly not have any effect at all.
>>>
>>> And when an application would have only explicitly assigned the fields known previously and then later been compiled with the new points field it would have failed.
>>>
>>> It is good practice to memset() structures given to the kernel so that all bytes are zero initialized, but it is not documented as mandatory as far as I know.
>>
>> Even though it may not be documented, it is in fact mandatory. Otherwise it's not possible to safely extend ioctl structs in general.
>
> The intention of the original patch was to ignore the args->points
> field if the flag is not set:
>
> if (args->flags & DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_TIMELINE)
> point = args->point;
>
> Using args->point unconditionally later was therefore a mistake.
There is precedence in the ioctl, the pad member is checked against zero for the same reason.
The check was there because it is invalid to pass when IMPORT/EXPORT_SYNC_FILE was not set.
This is what I would recommend instead:
----
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index 2d4ab745fdad9..176fac24a3198 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -857,7 +857,6 @@ drm_syncobj_handle_to_fd_ioctl(struct drm_device *dev, void *data,
struct drm_syncobj_handle *args = data;
unsigned int valid_flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_TIMELINE |
DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE;
- u64 point = 0;
if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ))
return -EOPNOTSUPP;
@@ -868,15 +867,14 @@ drm_syncobj_handle_to_fd_ioctl(struct drm_device *dev, void *data,
if (args->flags & ~valid_flags)
return -EINVAL;
- if (args->flags & DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_TIMELINE)
- point = args->point;
+ if (!(args->flags & DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_TIMELINE) &&
+ !(args->flags & DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE) &&
+ args->point)
+ return -EINVAL;
if (args->flags & DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE)
return drm_syncobj_export_sync_file(file_private, args->handle,
- point, &args->fd);
-
- if (args->point)
- return -EINVAL;
+ args->point, &args->fd);
return drm_syncobj_handle_to_fd(file_private, args->handle,
&args->fd);
@@ -889,7 +887,6 @@ drm_syncobj_fd_to_handle_ioctl(struct drm_device *dev, void *data,
struct drm_syncobj_handle *args = data;
unsigned int valid_flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE |
DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE;
- u64 point = 0;
if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ))
return -EOPNOTSUPP;
@@ -900,17 +897,16 @@ drm_syncobj_fd_to_handle_ioctl(struct drm_device *dev, void *data,
if (args->flags & ~valid_flags)
return -EINVAL;
- if (args->flags & DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE)
- point = args->point;
+ if (!(args->flags & DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_TIMELINE) &&
+ !(args->flags & DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE) &&
+ args->point)
+ return -EINVAL;
if (args->flags & DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE)
return drm_syncobj_import_sync_file_fence(file_private,
args->fd,
args->handle,
- point);
-
- if (args->point)
- return -EINVAL;
+ args->point);
return drm_syncobj_fd_to_handle(file_private, args->fd,
&args->handle);
next prev parent reply other threads:[~2026-03-03 16:40 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-01 12:34 [PATCH] drm/syncobj: Fix handle <-> fd ioctls with dirty stack Julian Orth
2026-03-02 11:27 ` Christian König
2026-03-02 11:54 ` Dmitry Osipenko
2026-03-03 11:17 ` Michel Dänzer
2026-03-03 11:23 ` Julian Orth
2026-03-03 11:38 ` Michel Dänzer
2026-03-03 11:41 ` Julian Orth
2026-03-03 14:53 ` Maarten Lankhorst
2026-03-03 14:59 ` Christian König
2026-03-03 15:15 ` Maarten Lankhorst
2026-03-03 15:21 ` Julian Orth
2026-03-03 17:02 ` Michel Dänzer
2026-03-03 15:29 ` Michel Dänzer
2026-03-03 15:36 ` Julian Orth
2026-03-03 16:40 ` Maarten Lankhorst [this message]
2026-03-03 16:54 ` Julian Orth
2026-03-03 17:04 ` Michel Dänzer
2026-03-03 17:11 ` Julian Orth
2026-03-03 17:18 ` Michel Dänzer
2026-03-03 17:30 ` Julian Orth
2026-03-03 17:44 ` Maarten Lankhorst
2026-03-03 18:53 ` Michel Dänzer
2026-03-03 19:12 ` Julian Orth
2026-03-04 9:57 ` Maarten Lankhorst
2026-03-04 11:15 ` Michel Dänzer
2026-03-04 11:25 ` Julian Orth
2026-03-04 11:47 ` Michel Dänzer
2026-03-04 12:32 ` Julian Orth
2026-03-04 14:29 ` Michel Dänzer
2026-03-04 14:35 ` Julian Orth
2026-03-05 9:47 ` Maarten Lankhorst
2026-03-03 17:40 ` Maarten Lankhorst
2026-03-03 17:44 ` Julian Orth
2026-03-03 19:58 ` David Laight
2026-03-04 10:35 ` Maarten Lankhorst
2026-03-03 17:05 ` Maarten Lankhorst
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=bc3417d9-d191-4cc7-95e0-968b0b9bec05@linux.intel.com \
--to=maarten.lankhorst@linux.intel.com \
--cc=airlied@gmail.com \
--cc=christian.koenig@amd.com \
--cc=dmitry.osipenko@collabora.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=ju.orth@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=michel.daenzer@mailbox.org \
--cc=mripard@kernel.org \
--cc=robin.clark@oss.qualcomm.com \
--cc=simona@ffwll.ch \
--cc=tzimmermann@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.