Author: marius
Date: Wed Feb 13 16:02:52 2019
New Revision: 344104
URL: https://svnweb.freebsd.org/changeset/base/344104

Log:
  MFC: r343372
  
  ixl(4): Fix handling data passed with ioctl from NVM update tool
  
  From Krzysztof:
  
  Ensure that the entire data buffer passed from the NVM update tool is copied 
in
  to kernel space and copied back out to user space using copyin() and 
copyout().
  
  PR:           234104
  Submitted by: Krzysztof Galazka <krzysztof.gala...@intel.com>
  Reported by:  Finn <ix...@riseup.net>
  Differential Revision:        https://reviews.freebsd.org/D18817

Modified:
  stable/12/sys/dev/ixl/ixl_pf_main.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/dev/ixl/ixl_pf_main.c
==============================================================================
--- stable/12/sys/dev/ixl/ixl_pf_main.c Wed Feb 13 15:46:05 2019        
(r344103)
+++ stable/12/sys/dev/ixl/ixl_pf_main.c Wed Feb 13 16:02:52 2019        
(r344104)
@@ -3664,23 +3664,34 @@ ixl_handle_nvmupd_cmd(struct ixl_pf *pf, struct ifdrv 
        struct i40e_nvm_access *nvma;
        device_t dev = pf->dev;
        enum i40e_status_code status = 0;
-       int perrno;
+       size_t nvma_size, ifd_len, exp_len;
+       int err, perrno;
 
        DEBUGFUNC("ixl_handle_nvmupd_cmd");
 
        /* Sanity checks */
-       if (ifd->ifd_len < sizeof(struct i40e_nvm_access) ||
+       nvma_size = sizeof(struct i40e_nvm_access);
+       ifd_len = ifd->ifd_len;
+
+       if (ifd_len < nvma_size ||
            ifd->ifd_data == NULL) {
                device_printf(dev, "%s: incorrect ifdrv length or data 
pointer\n",
                    __func__);
                device_printf(dev, "%s: ifdrv length: %zu, sizeof(struct 
i40e_nvm_access): %zu\n",
-                   __func__, ifd->ifd_len, sizeof(struct i40e_nvm_access));
+                   __func__, ifd_len, nvma_size);
                device_printf(dev, "%s: data pointer: %p\n", __func__,
                    ifd->ifd_data);
                return (EINVAL);
        }
 
-       nvma = (struct i40e_nvm_access *)ifd->ifd_data;
+       nvma = malloc(ifd_len, M_DEVBUF, M_WAITOK);
+       err = copyin(ifd->ifd_data, nvma, ifd_len);
+       if (err) {
+               device_printf(dev, "%s: Cannot get request from user space\n",
+                   __func__);
+               free(nvma, M_DEVBUF);
+               return (err);
+       }
 
        if (pf->dbg_mask & IXL_DBG_NVMUPD)
                ixl_print_nvm_cmd(dev, nvma);
@@ -3694,13 +3705,49 @@ ixl_handle_nvmupd_cmd(struct ixl_pf *pf, struct ifdrv 
                }
        }
 
-       if (!(pf->state & IXL_PF_STATE_ADAPTER_RESETTING)) {
-               // TODO: Might need a different lock here
-               // IXL_PF_LOCK(pf);
-               status = i40e_nvmupd_command(hw, nvma, nvma->data, &perrno);
-               // IXL_PF_UNLOCK(pf);
-       } else {
-               perrno = -EBUSY;
+       if (pf->state & IXL_PF_STATE_ADAPTER_RESETTING) {
+               free(nvma, M_DEVBUF);
+               return (-EBUSY);
+       }
+
+       if (nvma->data_size < 1 || nvma->data_size > 4096) {
+               device_printf(dev, "%s: invalid request, data size not in 
supported range\n",
+                   __func__);
+               free(nvma, M_DEVBUF);
+               return (EINVAL);
+       }
+
+       /*
+        * Older versions of the NVM update tool don't set ifd_len to the size
+        * of the entire buffer passed to the ioctl. Check the data_size field
+        * in the contained i40e_nvm_access struct and ensure everything is
+        * copied in from userspace.
+        */
+       exp_len = nvma_size + nvma->data_size - 1; /* One byte is kept in 
struct */
+
+       if (ifd_len < exp_len) {
+               ifd_len = exp_len;
+               nvma = realloc(nvma, ifd_len, M_DEVBUF, M_WAITOK);
+               err = copyin(ifd->ifd_data, nvma, ifd_len);
+               if (err) {
+                       device_printf(dev, "%s: Cannot get request from user 
space\n",
+                                       __func__);
+                       free(nvma, M_DEVBUF);
+                       return (err);
+               }
+       }
+
+       // TODO: Might need a different lock here
+       // IXL_PF_LOCK(pf);
+       status = i40e_nvmupd_command(hw, nvma, nvma->data, &perrno);
+       // IXL_PF_UNLOCK(pf);
+
+       err = copyout(nvma, ifd->ifd_data, ifd_len);
+       free(nvma, M_DEVBUF);
+       if (err) {
+               device_printf(dev, "%s: Cannot return data to user space\n",
+                               __func__);
+               return (err);
        }
 
        /* Let the nvmupdate report errors, show them only when debug is 
enabled */
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to