diff --git a/drivers/staging/android/ashmem_rust.rs b/drivers/staging/android/ashmem_rust.rs index ba1ebce05af0..ad8bb318e824 100644 --- a/drivers/staging/android/ashmem_rust.rs +++ b/drivers/staging/android/ashmem_rust.rs @@ -284,17 +284,16 @@ impl MiscDevice for Ashmem { } impl Ashmem { - fn set_name(&self, mut reader: UserSliceReader) -> Result { + fn set_name(&self, reader: UserSliceReader) -> Result { let mut local_name = [0u8; ASHMEM_NAME_LEN]; - reader.read_slice(&mut local_name)?; + let mut len = reader.strncpy_from_user(&mut local_name)?; - // Find the zero terminator. If the zero terminator is missing, the string is truncated to - // `ASHMEM_NAME_LEN-1` so that `get_name` can return it and has enough space to add a zero - // terminator. - let len = local_name - .iter() - .position(|&c| c == 0) - .unwrap_or(local_name.len() - 1); + // If the zero terminator is missing, the string is truncated to `ASHMEM_NAME_LEN-1` so + // that `get_name` can return it and has enough space to add a zero terminator. + if len == ASHMEM_NAME_LEN { + len -= 1; + local_name[len] = 0; + } let mut v = KVec::with_capacity(len, GFP_KERNEL)?; v.extend_from_slice(&local_name[..len], GFP_KERNEL)?; diff --git a/rust/kernel/uaccess.rs b/rust/kernel/uaccess.rs index 5a3c2d4df65f..e7ed6c412ab1 100644 --- a/rust/kernel/uaccess.rs +++ b/rust/kernel/uaccess.rs @@ -294,6 +294,19 @@ impl UserSliceReader { unsafe { buf.set_len(buf.len() + len) }; Ok(()) } + + /// Reads a nul-terminated string into the provided buffer and returns the length. + pub fn strncpy_from_user(self, buf: &mut [u8]) -> Result { + let max = usize::min(self.length, buf.len()) as isize; + // SAFETY: `buf` is valid for writing `buf.len()` bytes. + let res = + unsafe { bindings::strncpy_from_user(buf.as_mut_ptr(), self.ptr as *const u8, max) }; + if res >= 0 { + Ok(res as usize) + } else { + Err(Error::from_errno(res as i32)) + } + } } /// A writer for [`UserSlice`].