We add a new flag DRM_SYNCOBJ_*_FLAGS_TIMELINE and a point argument, but we never check if the point is only set when the timeline flag is set, and we still allow the timeline flag to be set when sync files are not used.
This was discovered when userspace increased the size of the ioctl to include args->point, but never cleared args->point, so fd_to_handle and handle_to_fd ioctl's without timeline started failing. Add more strict checking to prevent userspace from creating new bugs! Signed-off-by: Maarten Lankhorst <[email protected]> Fixes: c2d3a7300695 ("drm/syncobj: Extend EXPORT_SYNC_FILE for timeline syncobjs") Cc: Rob Clark <[email protected]> Cc: Julian Orth <[email protected]> Cc: Christian König <[email protected]> Cc: Michel Dänzer <[email protected]> --- drivers/gpu/drm/drm_syncobj.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 250734dee928e..33f2fc987e1d1 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,14 +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->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); + args->point, &args->fd); - if (args->point) + if (args->flags & DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_TIMELINE) return -EINVAL; return drm_syncobj_handle_to_fd(file_private, args->handle, @@ -889,7 +888,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,16 +898,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_FD_TO_HANDLE_FLAGS_TIMELINE) && 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); + args->point); - if (args->point) + if (args->flags & DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE) return -EINVAL; return drm_syncobj_fd_to_handle(file_private, args->fd, -- 2.51.0
