[PATCH v4 3/3] drm/tyr: allow userspace buffers to be mismatched
From: Deborah Brouwer
Date: Tue Oct 20 2026 - 20:09:44 EST
Allow userspace to provide a buffer that is smaller or larger than the
object that the kernel expects to write into it.
Set a minimum buffer size to match those in PANTHOR_UOBJ_MIN_SIZE. If
userspace provides at least the minimum buffer size, then simply write
until the buffer is full.
If userspace provides a larger buffer than necessary, then zero out the
remaining buffer.
This ensures UAPI compatibility with Panthor.
Signed-off-by: Deborah Brouwer <deborah.brouwer@xxxxxxxxxxxxx>
---
drivers/gpu/drm/tyr/file.rs | 49 +++++++++++++++++++++++++++++++++++++--------
1 file changed, 41 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/tyr/file.rs b/drivers/gpu/drm/tyr/file.rs
index ceadde976502..bf66238ea4c6 100644
--- a/drivers/gpu/drm/tyr/file.rs
+++ b/drivers/gpu/drm/tyr/file.rs
@@ -1,14 +1,18 @@
// SPDX-License-Identifier: GPL-2.0 or MIT
+use core::mem::offset_of;
+
use kernel::{
drm::{
self,
Registered, //
},
+ num::casts::FromSafeCast,
prelude::*,
uaccess::UserSlice,
uapi, //
};
+use zerocopy::Immutable;
use crate::driver::{
TyrDrmDevice,
@@ -16,6 +20,37 @@
TyrDrmRegistrationData, //
};
+trait UobjMinSize {
+ fn min_size(&self) -> usize;
+}
+
+impl UobjMinSize for uapi::drm_panthor_gpu_info {
+ fn min_size(&self) -> usize {
+ offset_of!(Self, tiler_present) + size_of_val(&self.tiler_present)
+ }
+}
+
+// If the user buffer is at least the minimum required size, then
+// copy as much of the kernel object as will fit into the user buffer.
+// Don't fail if the user buffer is smaller than the kernel object.
+// If the user buffer is bigger than needed, zero out the remainder.
+fn set_uobj<T: IntoBytes + Immutable>(
+ usr_dst: u64,
+ size: u32,
+ min_size: usize,
+ src_obj: &T,
+) -> Result {
+ let size = usize::from_safe_cast(size);
+ if size < min_size {
+ return Err(EINVAL);
+ }
+
+ let mut writer = UserSlice::new(UserPtr::from_u64(usr_dst), size).writer();
+ writer.write_slice_partial(src_obj.as_bytes(), 0)?;
+ writer.clear()?;
+ Ok(())
+}
+
#[pin_data]
pub(crate) struct TyrDrmFileData {}
@@ -48,14 +83,12 @@ pub(crate) fn dev_query(
} else {
match devquery.type_ {
uapi::drm_panthor_dev_query_type_DRM_PANTHOR_DEV_QUERY_GPU_INFO => {
- let mut writer = UserSlice::new(
- UserPtr::from_addr(devquery.pointer as usize),
- devquery.size as usize,
- )
- .writer();
-
- writer.write_slice(reg_data.gpu_info.as_bytes())?;
-
+ set_uobj(
+ devquery.pointer,
+ devquery.size,
+ reg_data.gpu_info.min_size(),
+ ®_data.gpu_info,
+ )?;
Ok(0)
}
_ => Err(EINVAL),
--
2.56.0