All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bastien Nocera <hadess@hadess.net>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org, bpf@vger.kernel.org,
	Alan Stern <stern@rowland.harvard.edu>,
	Benjamin Tissoires <benjamin.tissoires@redhat.com>,
	Peter Hutterer <peter.hutterer@who-t.net>,
	"Eric W . Biederman" <ebiederm@xmission.com>,
	Alexei Starovoitov <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Andrii Nakryiko <andrii@kernel.org>
Subject: Re: [PATCH 1/2] USB: core: add a way to revoke access to open USB devices
Date: Tue, 09 Aug 2022 13:18:43 +0200	[thread overview]
Message-ID: <d2dc546d771060b0a95d663fb77158d63b75bb9b.camel@hadess.net> (raw)
In-Reply-To: <YvI4em9fCdZgRPnY@kroah.com>

On Tue, 2022-08-09 at 12:35 +0200, Greg Kroah-Hartman wrote:
> On Tue, Aug 09, 2022 at 11:42:59AM +0200, Bastien Nocera wrote:
> > There is a need for userspace applications to open USB devices
> > directly,
> > for all the USB devices without a kernel-level class driver[1], and
> > implemented in user-space.
> > 
> > As not all devices are built equal, we want to be able to revoke
> > access to those devices whether it's because the user isn't at the
> > console anymore, or because the web browser, or sandbox doesn't
> > want
> > to allow access to that device.
> > 
> > This commit implements the internal API used to revoke access to
> > USB
> > devices, given either bus and device numbers, or/and a user's
> > effective UID.
> 
> Revoke what exactly?

Access.

>   You should be revoking the file descriptor that is
> open, not anything else as those are all transient and not uniquely
> identified and racy.

They're "unique enough" (tm). The 

> 
> 
> 
> > 
> > Signed-off-by: Bastien Nocera <hadess@hadess.net>
> > 
> > [1]:
> > Non exhaustive list of devices and device types that need raw USB
> > access:
> > - all manners of single-board computers and programmable chips and
> > devices (avrdude, STLink, sunxi bootloader, flashrom, etc.)
> > - 3D printers
> > - scanners
> > - LCD "displays"
> > - user-space webcam and still cameras
> > - game controllers
> > - video/audio capture devices
> > - sensors
> > - software-defined radios
> > - DJ/music equipment
> > - protocol analysers
> > - Rio 500 music player
> > ---
> >  drivers/usb/core/devio.c | 79
> > ++++++++++++++++++++++++++++++++++++++--
> >  drivers/usb/core/usb.h   |  2 +
> >  2 files changed, 77 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
> > index b5b85bf80329..d8d212ef581f 100644
> > --- a/drivers/usb/core/devio.c
> > +++ b/drivers/usb/core/devio.c
> > @@ -78,6 +78,7 @@ struct usb_dev_state {
> >         int not_yet_resumed;
> >         bool suspend_allowed;
> >         bool privileges_dropped;
> > +       bool revoked;
> >  };
> >  
> >  struct usb_memory {
> > @@ -183,6 +184,13 @@ static int connected(struct usb_dev_state *ps)
> >                         ps->dev->state != USB_STATE_NOTATTACHED);
> >  }
> >  
> > +static int disconnected_or_revoked(struct usb_dev_state *ps)
> > +{
> > +       return (list_empty(&ps->list) ||
> > +                       ps->dev->state == USB_STATE_NOTATTACHED ||
> > +                       ps->revoked);
> > +}
> > +
> >  static void dec_usb_memory_use_count(struct usb_memory *usbm, int
> > *count)
> >  {
> >         struct usb_dev_state *ps = usbm->ps;
> > @@ -237,6 +245,9 @@ static int usbdev_mmap(struct file *file,
> > struct vm_area_struct *vma)
> >         dma_addr_t dma_handle;
> >         int ret;
> >  
> > +       if (disconnected_or_revoked(ps))
> > +               return -ENODEV;
> > +
> >         ret = usbfs_increase_memory_usage(size + sizeof(struct
> > usb_memory));
> >         if (ret)
> >                 goto error;
> > @@ -310,7 +321,7 @@ static ssize_t usbdev_read(struct file *file,
> > char __user *buf, size_t nbytes,
> >  
> >         pos = *ppos;
> >         usb_lock_device(dev);
> > -       if (!connected(ps)) {
> > +       if (disconnected_or_revoked(ps)) {
> >                 ret = -ENODEV;
> >                 goto err;
> >         } else if (pos < 0) {
> > @@ -2315,7 +2326,7 @@ static int proc_ioctl(struct usb_dev_state
> > *ps, struct usbdevfs_ioctl *ctl)
> >         if (ps->privileges_dropped)
> >                 return -EACCES;
> >  
> > -       if (!connected(ps))
> > +       if (disconnected_or_revoked(ps))
> >                 return -ENODEV;
> >  
> >         /* alloc buffer */
> > @@ -2555,7 +2566,7 @@ static int proc_forbid_suspend(struct
> > usb_dev_state *ps)
> >  
> >  static int proc_allow_suspend(struct usb_dev_state *ps)
> >  {
> > -       if (!connected(ps))
> > +       if (disconnected_or_revoked(ps))
> >                 return -ENODEV;
> >  
> >         WRITE_ONCE(ps->not_yet_resumed, 1);
> > @@ -2580,6 +2591,66 @@ static int proc_wait_for_resume(struct
> > usb_dev_state *ps)
> >         return proc_forbid_suspend(ps);
> >  }
> >  
> > +static int usbdev_revoke(struct usb_dev_state *ps)
> > +{
> > +       struct usb_device *dev = ps->dev;
> > +       unsigned int ifnum;
> > +       struct async *as;
> > +
> > +       if (ps->revoked) {
> > +               usb_unlock_device(dev);
> > +               return -ENODEV;
> > +       }
> > +
> > +       snoop(&dev->dev, "%s: REVOKE by PID %d: %s\n", __func__,
> > +             task_pid_nr(current), current->comm);
> > +
> > +       ps->revoked = true;
> > +
> > +       for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps-
> > >ifclaimed);
> > +                       ifnum++) {
> > +               if (test_bit(ifnum, &ps->ifclaimed))
> > +                       releaseintf(ps, ifnum);
> > +       }
> > +       destroy_all_async(ps);
> > +
> > +       as = async_getcompleted(ps);
> > +       while (as) {
> > +               free_async(as);
> > +               as = async_getcompleted(ps);
> > +       }
> > +
> > +       wake_up(&ps->wait);
> > +
> > +       return 0;
> > +}
> > +
> > +int usb_revoke_for_euid(struct usb_device *udev,
> > +               int euid)
> > +{
> > +       struct usb_dev_state *ps;
> > +
> > +       usb_lock_device(udev);
> > +
> > +       list_for_each_entry(ps, &udev->filelist, list) {
> > +               if (euid >= 0) {
> > +                       kuid_t kuid;
> > +
> > +                       if (!ps || !ps->cred)
> > +                               continue;
> > +                       kuid = ps->cred->euid;
> 
> How is this handling uid namespaces?

The caller is supposed to be outside namespaces. It's a BPF programme,
so must be loaded by a privileged caller.

> 
> Again, just revoke the file descriptor, like the BSDs do for a tiny
> subset of device drivers.
> 
> This comes up ever so often, why does someone not just add real
> revoke(2) support to Linux to handle it if they really really want it
> (I
> tried a long time ago, but didn't have it in me as I had no real
> users
> for it...)

This was already explained twice, there's nothing to "hand out" those
file descriptors, so no one but the kernel and the programme itself
have that file descriptor, so it can't be used as an identifier.

  reply	other threads:[~2022-08-09 11:18 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-09  9:42 [PATCH 0/2] USB: core: add a way to revoke access to open USB devices Bastien Nocera
2022-08-09  9:42 ` [PATCH 1/2] " Bastien Nocera
2022-08-09 10:32   ` Greg Kroah-Hartman
2022-08-09 11:15     ` Bastien Nocera
2022-08-09 11:30       ` Greg Kroah-Hartman
2022-08-09 11:53         ` Bastien Nocera
2022-08-09 10:35   ` Greg Kroah-Hartman
2022-08-09 11:18     ` Bastien Nocera [this message]
2022-08-09 12:52       ` Greg Kroah-Hartman
2022-08-09 13:27         ` Bastien Nocera
2022-08-09 16:31           ` Greg Kroah-Hartman
2022-08-09 17:16             ` Bastien Nocera
2022-08-09 19:43           ` Alan Stern
2022-08-09 16:46   ` Eric W. Biederman
2022-08-09 17:08     ` Bastien Nocera
2022-08-10 17:18   ` kernel test robot
2022-08-10 17:28   ` kernel test robot
2022-08-09  9:43 ` [PATCH 2/2] usb: Implement usb_revoke() BPF function Bastien Nocera
2022-08-09 10:38   ` Greg Kroah-Hartman
2022-08-09 11:18     ` Bastien Nocera
2022-08-09 12:49       ` Greg Kroah-Hartman
2022-08-09 13:27         ` Bastien Nocera
2022-08-09 14:31     ` Bastien Nocera
2022-08-09 16:33       ` Greg Kroah-Hartman
2022-08-09 17:27         ` Bastien Nocera
2022-08-18 15:08           ` Greg Kroah-Hartman
2022-08-30 14:44             ` Bastien Nocera
2022-08-30 15:10               ` Greg Kroah-Hartman
2022-08-30 16:28                 ` Bastien Nocera
2022-08-09 17:22   ` Eric W. Biederman
2022-08-10 17:59   ` kernel test robot
2022-10-26 15:00   ` Bastien Nocera
2022-10-26 15:22     ` Greg Kroah-Hartman
2022-08-09 10:31 ` [PATCH 0/2] USB: core: add a way to revoke access to open USB devices Greg Kroah-Hartman
2022-08-09 11:15   ` Bastien Nocera
2022-08-09 11:29     ` Greg Kroah-Hartman
2022-08-09 17:25 ` Eric W. Biederman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d2dc546d771060b0a95d663fb77158d63b75bb9b.camel@hadess.net \
    --to=hadess@hadess.net \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=benjamin.tissoires@redhat.com \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=ebiederm@xmission.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=peter.hutterer@who-t.net \
    --cc=stern@rowland.harvard.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.