linux-staging.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
From: Arnd Bergmann <arnd@kernel.org>
To: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>,
	"Lad, Prabhakar" <prabhakar.csengg@gmail.com>,
	 Eduardo Valentin <edubezval@gmail.com>,
	Sakari Ailus <sakari.ailus@linux.intel.com>,
	 Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Vaibhav Gupta <vaibhavgupta40@gmail.com>,
	 Liu Shixin <liushixin2@huawei.com>,
	 Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
	 Jacopo Mondi <jacopo+renesas@jmondi.org>,
	 Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
	 Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	 Linux Media Mailing List <linux-media@vger.kernel.org>,
	linux-staging@lists.linux.dev
Subject: Re: [PATCH v2 2/7] media: v4l2-core: explicitly clear ioctl input data
Date: Fri, 11 Jun 2021 17:22:56 +0200	[thread overview]
Message-ID: <CAK8P3a2XbiU9SdafUapKABXJes8C5roLGKynL5LnGfTN3n=Evw@mail.gmail.com> (raw)
In-Reply-To: <a59eeddd-34bb-6b84-06b3-9fb1934d447e@xs4all.nl>

On Fri, Jun 11, 2021 at 2:05 PM Hans Verkuil <hverkuil-cisco@xs4all.nl> wrote:
> On 10/06/2021 23:43, Arnd Bergmann wrote:
> > @@ -3122,12 +3122,23 @@ static int video_get_user(void __user *arg, void *parg,
> >
> >       if (cmd == real_cmd) {
> >               if (copy_from_user(parg, (void __user *)arg, n))
> > -                     err = -EFAULT;
> > -     } else if (in_compat_syscall()) {
> > -             err = v4l2_compat_get_user(arg, parg, cmd);
> > -     } else {
> > -             switch (cmd) {
> > +                     return -EFAULT;
> > +
> > +             /* zero out anything we don't copy from userspace */
> > +             if (n < _IOC_SIZE(real_cmd))
> > +                     memset((u8 *)parg + n, 0, _IOC_SIZE(real_cmd) - n);
>
> This should always happen, not just when cmd == real_cmd.

Ok, got it. I was trying to simplify this, but I went a little too far, so
in the case of VIDIOC_QUERYBUF_TIME32 I dropped the final
clearing of the extra data, leaving the user data in place.

> The comment is a bit misleading: besides zeroing what isn't copied from
> userspace, it also zeroes copied fields based on INFO_FL_CLEAR_MASK.

I'm not following here, isn't that the same? We copy 'n' bytes, and then we
clear 'size - n' bytes, which is everything that wasn't copied.

> With this change that no longer happens and v4l2-compliance starts complaining.
>
> > +
> > +             return 0;
> > +     }
> > +
> > +     /* zero out whole buffer first to deal with missing emulation */
> > +     memset(parg, 0, _IOC_SIZE(real_cmd));
> > +
> > +     if (in_compat_syscall())
> > +             return v4l2_compat_get_user(arg, parg, cmd);
> > +
> >  #if !defined(CONFIG_64BIT) && defined(CONFIG_COMPAT_32BIT_TIME)
> > +     switch (cmd) {
> >               case VIDIOC_QUERYBUF_TIME32:
> >               case VIDIOC_QBUF_TIME32:
> >               case VIDIOC_DQBUF_TIME32:
>
> The 'case' statements need to be indented one tab less.

It seems this is no longer needed when I go back to having the switch()
inside the else{}.

> > @@ -3140,28 +3151,24 @@ static int video_get_user(void __user *arg, void *parg,
> >
> >                       *vb = (struct v4l2_buffer) {
> >                               .index          = vb32.index,
> > -                                     .type           = vb32.type,
> > -                                     .bytesused      = vb32.bytesused,
> > -                                     .flags          = vb32.flags,
> > -                                     .field          = vb32.field,
> > -                                     .timestamp.tv_sec       = vb32.timestamp.tv_sec,
> > -                                     .timestamp.tv_usec      = vb32.timestamp.tv_usec,
> > -                                     .timecode       = vb32.timecode,
> > -                                     .sequence       = vb32.sequence,
> > -                                     .memory         = vb32.memory,
> > -                                     .m.userptr      = vb32.m.userptr,
> > -                                     .length         = vb32.length,
> > -                                     .request_fd     = vb32.request_fd,
> > +                             .type           = vb32.type,
> > +                             .bytesused      = vb32.bytesused,
> > +                             .flags          = vb32.flags,
> > +                             .field          = vb32.field,
> > +                             .timestamp.tv_sec       = vb32.timestamp.tv_sec,
> > +                             .timestamp.tv_usec      = vb32.timestamp.tv_usec,
> > +                             .timecode       = vb32.timecode,
> > +                             .sequence       = vb32.sequence,
> > +                             .memory         = vb32.memory,
> > +                             .m.userptr      = vb32.m.userptr,
> > +                             .length         = vb32.length,
> > +                             .request_fd     = vb32.request_fd,
>
> Can you put these whitespace changes in a separate patch?

Sure.

> I ended up with this code, and then my tests passed:
>
>        if (cmd == real_cmd) {
>                 if (copy_from_user(parg, (void __user *)arg, n))
>                         return -EFAULT;
>         } else if (in_compat_syscall()) {
>                 memset(parg, 0, n);
>                 err = v4l2_compat_get_user(arg, parg, cmd);
>         } else {
> #if !defined(CONFIG_64BIT) && defined(CONFIG_COMPAT_32BIT_TIME)
>                 memset(parg, 0, n);
>                 switch (cmd) {
>                 case VIDIOC_QUERYBUF_TIME32:
>                 case VIDIOC_QBUF_TIME32:
>                 case VIDIOC_DQBUF_TIME32:
>                 case VIDIOC_PREPARE_BUF_TIME32: {
>                         struct v4l2_buffer_time32 vb32;
>                         struct v4l2_buffer *vb = parg;
>
>                         if (copy_from_user(&vb32, arg, sizeof(vb32)))
>                                 return -EFAULT;
>
>                         *vb = (struct v4l2_buffer) {
>                                 .index          = vb32.index,
>                                         .type           = vb32.type,
>                                         .bytesused      = vb32.bytesused,
>                                         .flags          = vb32.flags,
>                                         .field          = vb32.field,
>                                         .timestamp.tv_sec       = vb32.timestamp.tv_sec,
>                                         .timestamp.tv_usec      = vb32.timestamp.tv_usec,
>                                         .timecode       = vb32.timecode,
>                                         .sequence       = vb32.sequence,
>                                         .memory         = vb32.memory,
>                                         .m.userptr      = vb32.m.userptr,
>                                         .length         = vb32.length,
>                                         .request_fd     = vb32.request_fd,
>                         };
>                         break;
>                 }
>                 }
> #endif
>         }
>
>         /* zero out anything we don't copy from userspace */
>         if (!err && n < _IOC_SIZE(real_cmd))
>                 memset((u8 *)parg + n, 0, _IOC_SIZE(real_cmd) - n);
>
>         return err;

Ok, so this version just adds the two memset(), without any other
changes. That is clearly the safest change, and I'll send it like this
in v3.

> That said, I also ran the regression tests on a i686 VM, and there I got a
> bunch of failures, but that was *without* your patches, so I think something
> unrelated broke. I'll have to dig more into this in the next few days.
>
> But I wanted to get this out first, since this patch is clearly wrong.

Thanks a lot for taking a look and giving it an initial test. I have
updated the git tree at

git://git.kernel.org:/pub/scm/linux/kernel/git/arnd/playground.git
playground/v4l2-compat-ioctl

with the changes you pointed out. Let me know when you have found
out what was going on in the VM guest, and I'll send it as v3 or integrate
additional fixes that you find necessary.

     Arnd

  reply	other threads:[~2021-06-11 15:24 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-10 21:42 [PATCH v2 0/7] media: v4l2: compat ioctl fixes Arnd Bergmann
2021-06-10 21:42 ` [PATCH v2 1/7] media: v4l2-core: ignore native time32 ioctls on 64-bit Arnd Bergmann
2021-06-10 21:43 ` [PATCH v2 2/7] media: v4l2-core: explicitly clear ioctl input data Arnd Bergmann
2021-06-11 12:03   ` Hans Verkuil
2021-06-11 15:22     ` Arnd Bergmann [this message]
2021-06-14  8:00       ` Hans Verkuil
2021-06-10 21:43 ` [PATCH v2 3/7] media: subdev: remove VIDIOC_DQEVENT_TIME32 handling Arnd Bergmann
2021-06-10 21:43 ` [PATCH v2 4/7] media: v4l2-core: return -ENODEV from ioctl when not registered Arnd Bergmann
2021-06-10 21:43 ` [PATCH v2 5/7] media: atomisp: remove compat_ioctl32 code Arnd Bergmann
2021-06-10 21:43 ` [PATCH v2 6/7] media: subdev: fix compat_ioctl32 Arnd Bergmann
2021-06-10 21:43 ` [PATCH v2 7/7] media: subdev: disallow ioctl for saa6588/davinci Arnd Bergmann

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='CAK8P3a2XbiU9SdafUapKABXJes8C5roLGKynL5LnGfTN3n=Evw@mail.gmail.com' \
    --to=arnd@kernel.org \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=edubezval@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=hverkuil-cisco@xs4all.nl \
    --cc=jacopo+renesas@jmondi.org \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-staging@lists.linux.dev \
    --cc=liushixin2@huawei.com \
    --cc=mchehab@kernel.org \
    --cc=prabhakar.csengg@gmail.com \
    --cc=sakari.ailus@linux.intel.com \
    --cc=vaibhavgupta40@gmail.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).