bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: providing memory objects to users


From: Thomas Bushnell, BSG
Subject: Re: providing memory objects to users
Date: 11 Jun 2002 20:21:59 -0700
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.2

Marcus Brinkmann <marcus@gnu.org> writes:

> First I tried to use libpager.  This worked out ok, but what I did was
> probably wrong.  I allocated anonymous pages in pager_read_page, and
> filled those with the display information.  The information could then
> be read by the client, allright.  But when I tried to write to the
> anonymous pages, those changes weren't visible in the client.  I believe
> I misunderstood that, and that the only way to do this would be to map
> the memory object again and write to that instead of to the anonymous
> pages directly.  

Using libpager is a reasonable thing to do, in my opinion.

But you must use it properly! :)

pager_read_page provides a newly-allocated page to the caller, but the
caller completely consumes that page.  Once you return, you must
regard the page as deallocated.  Why?

If you look at libpager/data-request.c, you'll see what the caller of
pager_read_page looks like.  Note that the page is immediately handed
to memory_object_data_supply, and the DATA argument to that RPC is
marked "Dealloc[]" in mach/mach.defs.  That generates three args, the
actual page, the length, and a MiG deallocate flag--and
libpager/data-request.c sets the deallocate flag always.

So your writes to these "anonymous pages" were not writes to the
anonymous pages at all, but rather writes into random memory.

On to the next:

> Furthermore, I noticed that this version would deadlock
> when there were no callers and the kernel tried to swap out the page and
> return it to the console server.  I didn't try hard to find out what
> went wrong, but I still have the debugging output if you want it.

This has to be some kind of locking bug.  No clue what it is, but if
your code acquires pager locks...that's where to look.

And the next:

> This made me think of tmpfs, which doesn't use libpager, but the
> default pager directly.  This looked appropriate to me.  After all, I
> didn't want to have a redundant copy of the data in a backing store or
> whatever.  I didn't need to do paging.  

We want to get rid of the default pager.  But whatever we replace it
with should support uses like the one you want.

> And as I don't use libdiskfs, I
> don't need to link to libpager at all.  However, this version now
> doesn't work at all.  I tried to map in the memory via vm_map, but when
> I access it the server just hangs interruptible (it hangs in a similar
> way my first version hanged when I didn't have the pager RPCs served).

By "the server" you mean which program exactly?  The default pager,
the program that does the map, or the server that hands out the memory
object? 

If it's the program that does the map, then it's hanging because you
probably didn't give it a real valid memory object.

> So, the basic question is, am I on the right track?  Can I use the
> default pager for this without worrying about libpager at all?

Maybe.

> And how do I do that if it doesn't work as elementary as I show below?
> And, btw, why is getting pages from the default server a privileged
> operation?  

Because memory object ports are not well-protected in Mach.  If you
send random bogus requests to a memory object port, you can massively
confuse the server.  Hurd servers need to deal with this (but don't).
In the CMU world, memory object ports are generally not handed out to
random users at all (and instead servers execute vm_map operations on
behalf of their clients).

> This restricts tmpfs and the console server to the superuser
> which is silly.  How can this be solved?

By making the default pager more robust in the face of malicious users.

> Here the meat of what I did:
> 
>   err = default_pager_object_create (default_pager, &display->memobj,
>                                        display->allocsize);
>   err = vm_map (mach_task_self (), (vm_address_t *) &user,
>                 display->allocsize,
>               0, 1, display->memobj, 0, 0,
>               VM_PROT_READ | VM_PROT_WRITE,
>               VM_PROT_READ | VM_PROT_WRITE,
>               VM_INHERIT_NONE);

Well, what's the error return from the first call?




reply via email to

[Prev in Thread] Current Thread [Next in Thread]