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

[Xen-devel] Re: [PATCH 2/2] xen/gnt{dev, alloc}: reserve event channels for notify



On 10/25/2011 03:02 PM, Konrad Rzeszutek Wilk wrote:
>>> And cause the event channel refcnt to be set to zero and free it. And then
>>> causing the box to die - as the event channels for the physical IRQ might 
>>> have
>>> gotten free-ed.
>>>
>>
>> Not really. For a given valid event channel E, this will increase the refcnt 
>> by one
>> when i == E, and then decrease refcnt the next time evtchn_get succeeds (for 
>> some
>> other value of i).
> 
> Oh right. Hmm.. I am having this feeling that it still makes sense to 
> seperate the
> events that are allocated by grantdev/grantalloc from the ones that are done
> for in-kernel uses (such as IRQ, MSI, IPI, etc). Basically not trusting the 
> userland
> with its arguments as much as possible.
> 
> And yes, I do understand that you need to be a root user to use /dev/gnt*, but
> I started thinking about QEMU. And Fedora has this concept of making QEMU run 
> in its
> own SELinux container (and own user) - or perhaps I am confusing this with 
> containers..
> Anyhow it runs in one of those quasi-root-but-not-root. My thinking is that 
> it could
> be possible do with QEMU running under Xen too, but then we have to make sure
> that all /dev/gnt* ioctls are secure <hand-waving what secure means>.
> 
> It probably involves more than just what we discussed.

That same SELinux category-based isolation mechanism is also a good solution 
for xen
qemu-dm processes, although moving qemu to a stubdom provides better isolation 
since
SELinux currently cannot talk to XSM to determine what domains a particular 
qemu-dm 
process should be able to manipulate.

Only allowing event channels allocated by userspace to be used in gnt* notify is
a good idea, since there's no reason for userspace to need to manipulate an 
event
channel set up by the kernel.

>>
>>> Hm.. Perhaps the gntalloc and gntdev should keep track of which event 
>>> channels
>>> are OK to refcnt? Something like a whitelist? Granted at that point the 
>>> refcounting
>>> could as well be done by the API that sets up the event channels from the 
>>> userspace.
>>
>> Hmm. Perhaps have a magic value for refcount (-1?) that indicates evtchn_get 
>> is not
>> available. That would become the default value of refcnt, and evtchn.c would 
>> then
>> use evtchn_make_refcounted() to change the refcount to 1 and allow _get/_put 
>> to work.
> 
> How would that work when the IRQ subsystem (so everything is setup in the 
> kernel)
> gets an event? Would the refcount be for that -1.. oh. You would only set
> the refcnt when the _get/_put calls are made and not when in-kernel calls to 
> setup
> IRQs are done?
> 

Right. The reference count would be a dual-purpose field indicating if the event
channel is kernel-internal (value -1) or userspace-visible (reference count > 
0).
New event channels would start out at -1, and evtchn.c would change them to 1.

>>
>>> So the evtchn_ioctl is pretty smart. It uses "get_port_user" to get the list
>>> of events that belong to this user (and have been handed out). I think you
>>> need to use that in the gntalloc to double-check that the event channel is 
>>> not
>>> one of the kernel type.
>>>
>>>> +  }
>>>>  
>>>>    gref->notify.flags = 0;
>>>>  
>>>> @@ -396,6 +398,16 @@ static long gntalloc_ioctl_unmap_notify(struct 
>>>> gntalloc_file_private_data *priv,
>>>>            goto unlock_out;
>>>>    }
>>>>  
>>>> +  if (op.action & UNMAP_NOTIFY_SEND_EVENT) {
>>>> +          if (evtchn_get(op.event_channel_port)) {
>>>> +                  rc = -EINVAL;
>>>> +                  goto unlock_out;
>>>> +          }
>>>> +  }
>>>> +
>>>> +  if (gref->notify.flags & UNMAP_NOTIFY_SEND_EVENT)
>>>> +          evtchn_put(gref->notify.event);
>>>> +
>>>>    gref->notify.flags = op.action;
>>>>    gref->notify.pgoff = pgoff;
>>>>    gref->notify.event = op.event_channel_port;
>>>> diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
>>>> index f914b26..cfcc890 100644
>>>> --- a/drivers/xen/gntdev.c
>>>> +++ b/drivers/xen/gntdev.c
>>>> @@ -190,6 +190,7 @@ static void gntdev_put_map(struct grant_map *map)
>>>>  
>>>>    if (map->notify.flags & UNMAP_NOTIFY_SEND_EVENT) {
>>>>            notify_remote_via_evtchn(map->notify.event);
>>>> +          evtchn_put(map->notify.event);
>>>>    }
>>>>  
>>>>    if (map->pages) {
>>>> @@ -596,6 +597,16 @@ static long gntdev_ioctl_notify(struct gntdev_priv 
>>>> *priv, void __user *u)
>>>>            goto unlock_out;
>>>>    }
>>>>  
>>>> +  if (op.action & UNMAP_NOTIFY_SEND_EVENT) {
>>>> +          if (evtchn_get(op.event_channel_port)) {
>>>> +                  rc = -EINVAL;
>>>> +                  goto unlock_out;
>>>> +          }
>>>> +  }
>>>> +
>>>> +  if (map->notify.flags & UNMAP_NOTIFY_SEND_EVENT)
>>>
>>> So notify.flags has not been set yet? That looks to be done later?
>>
>> Yep. It's the previous value (zero if we haven't called the ioctl yet).
> 
> OK, can you add a tiny comment so that in a year time the person reading this
> will have a warm fuzzy feeling..

OK

>>
>>> Or is this in case of the user doing
>>>
>>>  uargs.action = UNMAP_NOTIFY_SEND_EVENT;
>>>  ioctl(.., IOCTL_GNTALLOC_SET_UNMAP_NOTIFY, &uarg);
>>>  uargs.action = UNAMP_NOTIFY_CLEAR_BYTE;
>>>  ioctl(.., IOCTL_GNTALLOC_SET_UNMAP_NOTIFY, &uarg);
>>>
>>>  and we want to preserve the "old" flags before swapping over to the
>>> new?
>>
>> No. We acquire the new event channel before releasing the old one so that
>> if we happen to be the only one holding a reference to this event channel,
>> a change in the byte-clear portion of the notify does not cause us to drop
>> the event channel.
> 
> Ok.
>>
>>>> +          evtchn_put(map->notify.event);
>>>> +
>>>>    map->notify.flags = op.action;
>>>>    map->notify.addr = op.index - (map->index << PAGE_SHIFT);
>>>>    map->notify.event = op.event_channel_port;
>>>> -- 
>>>> 1.7.6.4

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.