Skip to content
Snippets Groups Projects
Commit af36ae12 authored by Anhad Singh's avatar Anhad Singh :crab:
Browse files

fix(mremap): fix referencing


Before it was first add_ref'ed by `borrow_frame_enforce_rw_allocated`,
manually and then by `allocated_shared_one_page`.

Now it is only done by `borrow_frame_enforce_rw_allocated` and does not
get unref-ed as take() is called on the returned `RaiiFrame`.

Now the page is manually mapped and an `Allocated` type grant is
constructed (synonymous to `MAP_PRIVATE`). Before by using `allocated_shared_one_page`
an `AllocatedShared` provided grant was constructed (synonymous to
`MAP_SHARED`), which was wrong as the TCB would've not got CoW-ed
after fork(), making the Tcb malformed.

Signed-off-by: default avatarAnhad Singh <andypython@protonmail.com>
parent 08231eb4
No related branches found
No related tags found
1 merge request!364feat(mremap): `KEEP_OLD`
......@@ -1102,6 +1102,22 @@ pub struct GrantFileRef {
impl Grant {
// TODO: PageCount newtype, to avoid confusion between bytes and pages?
// `base` must be mapped by the caller.
pub fn allocated_one_page_nomap(base: Page, flags: PageFlags<RmmA>) -> Grant {
Grant {
base,
info: GrantInfo {
page_count: 1,
flags,
mapped: true,
provider: Provider::Allocated {
cow_file_ref: None,
phys_contiguous: false,
},
},
}
}
// TODO: is_pinned
pub fn allocated_shared_one_page(
frame: Frame,
......
......@@ -9,10 +9,9 @@ use crate::{
context::{
self,
file::{FileDescription, FileDescriptor, InternalFlags},
memory::{AddrSpace, PageSpan},
memory::{AddrSpace, GenericFlusher, Grant, PageSpan, TlbShootdownActions},
process,
},
memory::AddRefError,
paging::{Page, VirtualAddress, PAGE_SIZE},
scheme::{self, CallerCtx, FileHandle, KernelScheme, OpenResult},
syscall::{data::Stat, error::*, flag::*},
......@@ -500,16 +499,8 @@ pub fn mremap(
if new_page_count != 1 {
return Err(Error::new(EOPNOTSUPP));
}
let raii_frame = addr_space.borrow_frame_enforce_rw_allocated(src_span.base)?;
let info = crate::memory::get_page_info(raii_frame.get()).ok_or(Error::new(EINVAL))?;
match info.add_ref(crate::memory::RefKind::Shared) {
Ok(()) => (),
Err(AddRefError::RcOverflow) => return Err(Error::new(ENOMEM)),
Err(AddRefError::CowToShared) => return Err(Error::new(EINVAL)),
Err(AddRefError::SharedToCow) => unreachable!(),
}
let raii_frame = addr_space.borrow_frame_enforce_rw_allocated(src_span.base)?;
let base = addr_space.acquire_write().mmap(
&addr_space,
......@@ -518,14 +509,19 @@ pub fn mremap(
map_flags,
&mut Vec::new(),
|page, page_flags, mapper, flusher| {
crate::context::memory::Grant::allocated_shared_one_page(
raii_frame.take(),
page,
page_flags,
mapper,
flusher,
false,
)
let frame = raii_frame.take();
// XXX: add_ref(RefKind::Shared) is internally done by borrow_frame_enforce_rw_allocated(src_span.base).
// The page does not get unref-ed as we call take() on the `raii_frame`.
unsafe {
mapper
.map_phys(page.start_address(), frame.base(), page_flags)
.ok_or(Error::new(ENOMEM))?
.ignore();
flusher.queue(frame, None, TlbShootdownActions::NEW_MAPPING);
}
Ok(Grant::allocated_one_page_nomap(page, page_flags))
},
)?;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment