ANDROID: ashmem: use strncpy_from_user in set_name
Ashmem expected that it could always read ASHMEM_NAME_LEN bytes from the provided pointer even if the actual string was shorter. This assumption turns out to be false. Bug: 409422661 Change-Id: I617be6c91947d44ec80b894c41fabe0f5c539eae Signed-off-by: Alice Ryhl <aliceryhl@google.com>
This commit is contained in:
committed by
Treehugger Robot
parent
56dea476ea
commit
ba971cd36a
@@ -284,17 +284,16 @@ impl MiscDevice for Ashmem {
|
||||
}
|
||||
|
||||
impl Ashmem {
|
||||
fn set_name(&self, mut reader: UserSliceReader) -> Result<isize> {
|
||||
fn set_name(&self, reader: UserSliceReader) -> Result<isize> {
|
||||
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)?;
|
||||
|
||||
@@ -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<usize> {
|
||||
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`].
|
||||
|
||||
Reference in New Issue
Block a user