AK+Kernel: Introduce StdLib function to copy FixedStringBuffer to user

This new Kernel StdLib function will be used to copy contents of a
FixedStringBuffer with a null character to a user process.

The first user of this new function is the prctl option of
PR_GET_PROCESS_NAME which would copy a process name including a null
character to a user provided buffer.
This commit is contained in:
Liav A 2023-08-23 21:10:02 +03:00 committed by Tim Schumacher
parent 6cb88e224e
commit 72231b405a
Notes: sideshowbarker 2024-07-17 01:04:03 +09:00
3 changed files with 19 additions and 5 deletions

View File

@ -95,8 +95,13 @@ public:
return m_storage.span();
}
StringView representable_view() const { return StringView(m_storage.data(), m_stored_length); }
Span<u8 const> span_view_ensuring_ending_null_char()
{
VERIFY(m_stored_length + 1 <= Size);
m_storage[m_stored_length] = '\0';
return Span<u8 const>(m_storage.data(), m_stored_length + 1);
}
size_t fixed_length() const { return Size; }
size_t stored_length() const { return m_stored_length; }
FixedStringBuffer()

View File

@ -201,3 +201,14 @@ inline ErrorOr<T> copy_typed_from_user(Userspace<T*> user_data)
TRY(copy_from_user(&data, user_data));
return data;
}
template<size_t Size>
ErrorOr<void> copy_fixed_string_buffer_including_null_char_to_user(Userspace<char*> dest, size_t buffer_size, FixedStringBuffer<Size> const& buffer)
{
FixedStringBuffer<Size + 1> name_with_null_char {};
name_with_null_char.store_characters(buffer.representable_view());
if (name_with_null_char.stored_length() + 1 > buffer_size)
return ENAMETOOLONG;
auto name_with_null_char_view = name_with_null_char.span_view_ensuring_ending_null_char();
return copy_to_user(dest, name_with_null_char_view.data(), name_with_null_char_view.size());
}

View File

@ -66,10 +66,8 @@ ErrorOr<FlatPtr> Process::sys$prctl(int option, FlatPtr arg1, FlatPtr arg2)
Userspace<char*> buffer = arg1;
size_t buffer_size = static_cast<size_t>(arg2);
TRY(m_name.with([&buffer, buffer_size](auto& name) -> ErrorOr<void> {
auto view = name.representable_view();
if (view.length() + 1 > buffer_size)
return ENAMETOOLONG;
return copy_to_user(buffer, view.characters_without_null_termination(), view.length() + 1);
VERIFY(!name.representable_view().is_null());
return copy_fixed_string_buffer_including_null_char_to_user(buffer, buffer_size, name);
}));
return 0;
}