return 0;
 }
 
+/*
+ * Copy a request from userspace. If the provided 'req' is larger than the
+ * user buffer then the user buffer is zero extended into the 'req'. If 'req'
+ * is smaller than the user buffer then the uncopied bytes in the user buffer
+ * must be zero.
+ */
+static int uverbs_request(struct uverbs_attr_bundle *attrs, void *req,
+                         size_t req_len)
+{
+       if (copy_from_user(req, attrs->ucore.inbuf,
+                          min(attrs->ucore.inlen, req_len)))
+               return -EFAULT;
+
+       if (attrs->ucore.inlen < req_len) {
+               memset(req + attrs->ucore.inlen, 0,
+                      req_len - attrs->ucore.inlen);
+       } else if (attrs->ucore.inlen > req_len) {
+               if (!ib_is_buffer_cleared(attrs->ucore.inbuf + req_len,
+                                         attrs->ucore.inlen - req_len))
+                       return -EOPNOTSUPP;
+       }
+       return 0;
+}
+
 static struct ib_uverbs_completion_event_file *
 _ib_uverbs_lookup_comp_file(s32 fd, const struct uverbs_attr_bundle *attrs)
 {
        struct ib_device *ib_dev;
        int ret;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        mutex_lock(&file->ucontext_lock);
        ib_dev = srcu_dereference(file->device->ib_dev,
        struct ib_uverbs_query_device      cmd;
        struct ib_uverbs_query_device_resp resp;
        struct ib_ucontext *ucontext;
+       int ret;
 
        ucontext = ib_uverbs_get_ucontext(attrs);
        if (IS_ERR(ucontext))
                return PTR_ERR(ucontext);
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        memset(&resp, 0, sizeof resp);
        copy_query_dev_fields(ucontext, &resp, &ucontext->device->attrs);
                return PTR_ERR(ucontext);
        ib_dev = ucontext->device;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        ret = ib_query_port(ib_dev, cmd.port_num, &attr);
        if (ret)
        int                            ret;
        struct ib_device *ib_dev;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        uobj = uobj_alloc(UVERBS_OBJECT_PD, attrs, &ib_dev);
        if (IS_ERR(uobj))
                                const char __user *buf, int in_len, int out_len)
 {
        struct ib_uverbs_dealloc_pd cmd;
+       int ret;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        return uobj_perform_destroy(UVERBS_OBJECT_PD, cmd.pd_handle, attrs);
 }
        int                             new_xrcd = 0;
        struct ib_device *ib_dev;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        mutex_lock(&ibudev->xrcd_tree_mutex);
 
                                const char __user *buf, int in_len, int out_len)
 {
        struct ib_uverbs_close_xrcd cmd;
+       int ret;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        return uobj_perform_destroy(UVERBS_OBJECT_XRCD, cmd.xrcd_handle, attrs);
 }
        int                          ret;
        struct ib_device *ib_dev;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK))
                return -EINVAL;
        int                          ret;
        struct ib_uobject           *uobj;
 
-       if (copy_from_user(&cmd, buf, sizeof(cmd)))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        if (cmd.flags & ~IB_MR_REREG_SUPPORTED || !cmd.flags)
                return -EINVAL;
                              const char __user *buf, int in_len, int out_len)
 {
        struct ib_uverbs_dereg_mr cmd;
+       int ret;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        return uobj_perform_destroy(UVERBS_OBJECT_MR, cmd.mr_handle, attrs);
 }
        int                            ret;
        struct ib_device *ib_dev;
 
-       if (copy_from_user(&cmd, buf, sizeof(cmd)))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        uobj = uobj_alloc(UVERBS_OBJECT_MW, attrs, &ib_dev);
        if (IS_ERR(uobj))
                                const char __user *buf, int in_len, int out_len)
 {
        struct ib_uverbs_dealloc_mw cmd;
+       int ret;
 
-       if (copy_from_user(&cmd, buf, sizeof(cmd)))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        return uobj_perform_destroy(UVERBS_OBJECT_MW, cmd.mw_handle, attrs);
 }
        struct ib_device *ib_dev;
        int ret;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        uobj = uobj_alloc(UVERBS_OBJECT_COMP_CHANNEL, attrs, &ib_dev);
        if (IS_ERR(uobj))
        struct ib_uverbs_create_cq      cmd;
        struct ib_uverbs_ex_create_cq   cmd_ex;
        struct ib_ucq_object           *obj;
+       int ret;
 
-       if (copy_from_user(&cmd, buf, sizeof(cmd)))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        memset(&cmd_ex, 0, sizeof(cmd_ex));
        cmd_ex.user_handle = cmd.user_handle;
        struct ib_cq                    *cq;
        int                             ret = -EINVAL;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
        if (!cq)
        struct ib_wc                   wc;
        int                            ret;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
        if (!cq)
 {
        struct ib_uverbs_req_notify_cq cmd;
        struct ib_cq                  *cq;
+       int ret;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
        if (!cq)
        struct ib_uverbs_destroy_cq_resp resp;
        struct ib_uobject               *uobj;
        struct ib_ucq_object            *obj;
+       int ret;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        uobj = uobj_get_destroy(UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
        if (IS_ERR(uobj))
 {
        struct ib_uverbs_create_qp      cmd;
        struct ib_uverbs_ex_create_qp   cmd_ex;
+       int ret;
 
-       if (copy_from_user(&cmd, buf, sizeof(cmd)))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        memset(&cmd_ex, 0, sizeof(cmd_ex));
        cmd_ex.user_handle = cmd.user_handle;
        int ret;
        struct ib_device *ib_dev;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        obj = (struct ib_uqp_object *)uobj_alloc(UVERBS_OBJECT_QP, attrs,
                                                 &ib_dev);
        struct ib_qp_init_attr         *init_attr;
        int                            ret;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        attr      = kmalloc(sizeof *attr, GFP_KERNEL);
        init_attr = kmalloc(sizeof *init_attr, GFP_KERNEL);
                               const char __user *buf, int in_len, int out_len)
 {
        struct ib_uverbs_ex_modify_qp cmd = {};
+       int ret;
 
-       if (copy_from_user(&cmd.base, buf, sizeof(cmd.base)))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd.base, sizeof(cmd.base));
+       if (ret)
+               return ret;
 
        if (cmd.base.attr_mask &
            ~((IB_USER_LEGACY_LAST_QP_ATTR_MASK << 1) - 1))
        struct ib_uverbs_destroy_qp_resp resp;
        struct ib_uobject               *uobj;
        struct ib_uqp_object            *obj;
+       int ret;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        uobj = uobj_get_destroy(UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
        if (IS_ERR(uobj))
        int ret;
        struct ib_device *ib_dev;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        uobj = uobj_alloc(UVERBS_OBJECT_AH, attrs, &ib_dev);
        if (IS_ERR(uobj))
                                const char __user *buf, int in_len, int out_len)
 {
        struct ib_uverbs_destroy_ah cmd;
+       int ret;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        return uobj_perform_destroy(UVERBS_OBJECT_AH, cmd.ah_handle, attrs);
 }
        struct ib_uverbs_mcast_entry *mcast;
        int                           ret;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
        if (!qp)
        int                           ret = -EINVAL;
        bool                          found = false;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
        if (!qp)
 {
        struct ib_uverbs_create_srq      cmd;
        struct ib_uverbs_create_xsrq     xcmd;
+       int ret;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        memset(&xcmd, 0, sizeof(xcmd));
        xcmd.response    = cmd.response;
                                 int out_len)
 {
        struct ib_uverbs_create_xsrq     cmd;
+       int ret;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        return __uverbs_create_xsrq(attrs, &cmd, &attrs->driver_udata);
 }
        struct ib_srq_attr          attr;
        int                         ret;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs);
        if (!srq)
        struct ib_srq                   *srq;
        int                             ret;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs);
        if (!srq)
        struct ib_uverbs_destroy_srq_resp resp;
        struct ib_uobject                *uobj;
        struct ib_uevent_object          *obj;
+       int ret;
 
-       if (copy_from_user(&cmd, buf, sizeof cmd))
-               return -EFAULT;
+       ret = uverbs_request(attrs, &cmd, sizeof(cmd));
+       if (ret)
+               return ret;
 
        uobj = uobj_get_destroy(UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs);
        if (IS_ERR(uobj))