[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



> > 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.
> 
> > 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?


> 
> > 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..
> 
> > 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
> > 
> 
> 
> -- 
> Daniel De Graaf
> National Security Agency

_______________________________________________
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®.