Re: [GIT PULL] kdbus for 4.1-rc1

David Herrmann
2015-04-21T14:01:06Z

Hi

On Tue, Apr 21, 2015 at 2:20 PM, Michal Hocko <mhocko@suse.cz> wrote:
> On Tue 21-04-15 12:17:49, David Herrmann wrote:
>> Hi
>>
>> On Tue, Apr 21, 2015 at 11:35 AM, One Thousand Gnomes
>> <gnomes@lxorguk.ukuu.org.uk> wrote:
>> >> On top of that, I think that someone into resource management needs to
>> >> seriously consider whether having a broadcast send do get_user_pages
>> >> or the equivalent on pages supplied by untrusted recipients (plural!)
>> >> is a good idea.
>> >
>> > Oh but its so much fun if you pass pages belonging to a device driver, or
>> > pass bits of a GEM object thereby keeping entire graphics textures
>> > referenced 8)
>>
>> We do not use GUP, nor do we pass around pinned pages. All we use is
>> __vfs_read() / __vfs_write() on shmem. Whether generic_file_write() /
>> copy_from_user() internally relies on GUP or not, is an orthogonal
>> issue that does not belong here.
>
> It kind of does AFAIU.

No, it is not. The issue with GUP is that you elevate the page
ref-count and thus prevent lru isolation, sealing, whatsoever. I
cannot see how it is related to kdbus. However, ...

> If for nothing else then the memcg reasons mentioned in
> other email (http://marc.info/?l=linux-kernel&m=142953380508188). If an
> untrusted user is allowed to hand over a shmem backed buffer which hasn't
> been charged yet (read faulted in) and then kdbus forced to fault it in
> a different user's context then you basically allow to hide memory
> allocations from the memcg. That is a clear show stopper.
>
> Or have I misunderstood the way how shmem buffers are used here?

..as you mentioned memcg, lets figure that out here. shmem buffers are
used as receive-buffers by kdbus peers. They are read-only to
user-space. All allocations are done by the kernel on message passing.
There is no buffering on the sender's side, only on the receiver's.

There're 3 possible ways to charge for memory that backs a message. We
can charge the sender, the receiver or the kernel. Right now we charge
the sender, as DBus-method-calls imply a trust relationship on the
target. We could as well charge the receiver, which might be
conceptually superior. Anyhow, both are imo better than the
dbus-daemon model, where we basically charge the root-memcg (more
precisely, the memcg of dbus-daemon).

Note that a message is always charged on either the sender or the
receiver. I don't see how memory is hidden from the memcg. If you pass
a memfd to another peer, you also need to be aware that this memory
was charged on you and stays so until the remote peer drops its
reference. But all messages you receive via kdbus are always
read-only.
Btw., binder avoids this issue by not charging anyone, which I also
don't think is a viable solution.

Could you elaborate on the exact issue you're seeing here?

Thanks
David