[libcamera-devel] [PATCH] v4l2: v4l2_camera_proxy: Prevent ioctl sign-extensions

Kieran Bingham kieran.bingham at ideasonboard.com
Tue Jul 11 12:26:56 CEST 2023


Quoting Kieran Bingham (2023-07-11 10:20:14)
> Hi Jacopo,
> 
> On 11/07/2023 10:06, Jacopo Mondi wrote:
> > Hi Kieran
> > 
> > On Wed, Jul 05, 2023 at 12:22:48AM +0100, Kieran Bingham via libcamera-devel wrote:
> >> Handling ioctl's within applications is often wrapped with a helper such
> >> as xioctl. Unfortunately, there are many instances of xioctl which
> >> incorrectly handle the correct size of the ioctl request.
> >>
> >> This leads to incorrect sign-extension of ioctl's which have bit-31 set,
> > 
> > I would expect this if the function arguments were signed, but does
> > sign-extension happens with unsigned arguments as well ?
> 
> The issue is in the caller - not this function. This patch aims to 
> handle things in the same way the kernel does (which only processes 32 
> bits of the data).
> 
> For instance, the linux kernel documentation has a sample implementation 
> of xioctl that would cause the fault that this patch fixes:
> 
> https://www.kernel.org/doc/html/v4.11/media/uapi/v4l/capture.c.html
> 
> static int xioctl(int fh, int request, void *arg)
> {
>          int r;
> 
>          do {
>                  r = ioctl(fh, request, arg);
>          } while (-1 == r && EINTR == errno);
> 
>          return r;
> }
> 
> If an application uses that xioctl, with the 'int request' and calls
> 
>    if (xioctl(vid_source, VIDIOC_QUERYCAP, &vid_source->cap) < 0) {
>    }
> 
> The VIDIOC_QUERYCAP (0x80685600) gets sign extended into 
> (0xffffffff80685600) and then doesn't match the parsing in the V4L2 
> adaptation layer.
> 
> 
> > 
> >> and can cause values to be passed into the libcamera's v4l2 adaptation
> >> layer which no longer represent the true IOCTL code.
> >>
> >> Match the implementation of the Linux kernel and ensure that only 32
> >> bits of the ioctl request are used by assigning to an unsigned int.
> >>
> 
> I'll add:
> 
> Link: https://github.com/Motion-Project/motion/discussions/1636
> 
> >> Signed-off-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
> >> ---
> >> This is a (simpler) rework of the previous patch [0]:
> >>   v4l2: v4l2_camera_proxy: Detect ioctl sign-extensions
> >>
> >> [0] https://patchwork.libcamera.org/patch/18311/
> >>
> >>   src/v4l2/v4l2_camera_proxy.cpp | 12 +++++++++++-
> >>   1 file changed, 11 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp
> >> index 55ff62cdb430..dfb672080219 100644
> >> --- a/src/v4l2/v4l2_camera_proxy.cpp
> >> +++ b/src/v4l2/v4l2_camera_proxy.cpp
> >> @@ -778,10 +778,20 @@ const std::set<unsigned long> V4L2CameraProxy::supportedIoctls_ = {
> >>      VIDIOC_STREAMOFF,
> >>   };
> >>
> >> -int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *arg)
> >> +int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long longRequest, void *arg)
> >>   {
> >>      MutexLocker locker(proxyMutex_);
> >>
> >> +    /*
> >> +     * The Linux Kernel only processes 32 bits of an IOCTL.
> >> +     *
> >> +     * Prevent unexpected sign-extensions that could occur if applications
> >> +     * use an unsigned int for the ioctl request, which would sign-extend

Aha, perhaps your comment was here and this should actually read:

	"if applications use a signed int for the ioctl request"

I'll s/unsigned int/signed int/

--
Kieran


> >> +     * to an incorrect value for unsigned longs on 64 bit architectures by
> >> +     * explicitly casting as an unsigned int here.
> >> +     */
> >> +    unsigned int request = longRequest;
> >> +
> >>      if (!arg && (_IOC_DIR(request) & _IOC_WRITE)) {
> >>              errno = EFAULT;
> >>              return -1;
> >> --
> >> 2.34.1
> >>


More information about the libcamera-devel mailing list