Pull rdma fixes from Jason Gunthorpe: "Several significant bug fixes of pre-existing issues: - Missing validation on ucap fd types passed from userspace - Missing validation of HW DMA space vs userpace expected sizes in EFA queue setup - DMA corruption when using DMA block sizes >= 4G when setting up MRs in all drivers - Missing validation of CPU IDs when setting up dma handles - Missing validation of IB_MR_REREG_ACCESS when changing writability of a MR - Missing validation of received message/packet size in ISER and SRP" * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: RDMA/srp: bound SRP_RSP sense copy by the received length IB/isert: Reject login PDUs shorter than ISER_HEADERS_LEN RDMA: During rereg_mr ensure that REREG_ACCESS is compatible RDMA/core: Validate cpu_id against nr_cpu_ids in DMAH alloc RDMA/umem: Fix truncation for block sizes >= 4G RDMA/efa: Validate SQ ring size against max LLQ size RDMA/core: Validate the passed in fops for ib_get_ucaps()
Unified · Split
| @@ -19,8 +19,8 @@ EXPORT_SYMBOL(__rdma_block_iter_start); · 18 unmodified lines | ||
| 19 | 19 | |
| 20 | 20 | bool __rdma_block_iter_next(struct ib_block_iter *biter) |
| 21 | 21 | { |
| 22 | − unsigned int block_offset; | |
| 23 | − unsigned int delta; | |
| 22 | + dma_addr_t block_offset; | |
| 23 | + dma_addr_t delta; | |
| 24 | 24 | |
| 25 | 25 | if (!biter->__sg_nents || !biter->__sg) |
| 26 | 26 | return false; |
| @@ -82,14 +82,12 @@ static int get_ucap_from_devt(dev_t devt, u64 *idx_mask) · 81 unmodified lines | ||
| 82 | 82 | |
| 83 | 83 | static int get_devt_from_fd(unsigned int fd, dev_t *ret_dev) |
| 84 | 84 | { |
| 85 | − struct file *file; | |
| 85 | + CLASS(fd, f)(fd); | |
| 86 | 86 | |
| 87 | − file = fget(fd); | |
| 88 | − if (!file) | |
| 87 | + if (fd_empty(f) || fd_file(f)->f_op != &ucaps_cdev_fops) | |
| 89 | 88 | return -EBADF; |
| 90 | 89 | |
| 91 | − *ret_dev = file_inode(file)->i_rdev; | |
| 92 | − fput(file); | |
| 90 | + *ret_dev = file_inode(fd_file(f))->i_rdev; | |
| 93 | 91 | return 0; |
| 94 | 92 | } |
| 95 | 93 | |
| @@ -332,3 +332,19 @@ int ib_umem_copy_from(void *dst, struct ib_umem *umem, size_t offset, · 331 unmodified lines | ||
| 332 | 332 | return 0; |
| 333 | 333 | } |
| 334 | 334 | EXPORT_SYMBOL(ib_umem_copy_from); |
| 335 | + | |
| 336 | +/* | |
| 337 | + * Called during rereg mr if the driver is able to re-use a umem for | |
| 338 | + * IB_MR_REREG_ACCESS. | |
| 339 | + */ | |
| 340 | +int ib_umem_check_rereg(struct ib_umem *umem, int flags, int new_access_flags) | |
| 341 | +{ | |
| 342 | + if (!umem) | |
| 343 | + return 0; | |
| 344 | + | |
| 345 | + if ((flags & IB_MR_REREG_ACCESS) && !(flags & IB_MR_REREG_TRANS)) | |
| 346 | + if (ib_access_writable(new_access_flags) && !umem->writable) | |
| 347 | + return -EACCES; | |
| 348 | + return 0; | |
| 349 | +} | |
| 350 | +EXPORT_SYMBOL(ib_umem_check_rereg); | |
| @@ -47,6 +47,11 @@ static int UVERBS_HANDLER(UVERBS_METHOD_DMAH_ALLOC)( · 46 unmodified lines | ||
| 47 | 47 | if (ret) |
| 48 | 48 | goto err; |
| 49 | 49 | |
| 50 | + if (dmah->cpu_id >= nr_cpu_ids) { | |
| 51 | + ret = -EINVAL; | |
| 52 | + goto err; | |
| 53 | + } | |
| 54 | + | |
| 50 | 55 | if (!cpumask_test_cpu(dmah->cpu_id, current->cpus_ptr)) { |
| 51 | 56 | ret = -EPERM; |
| 52 | 57 | goto err; |
| @@ -613,7 +613,8 @@ err_remove_mmap: · 612 unmodified lines | ||
| 613 | 613 | } |
| 614 | 614 | |
| 615 | 615 | static int efa_qp_validate_cap(struct efa_dev *dev, |
| 616 | − struct ib_qp_init_attr *init_attr) | |
| 616 | + struct ib_qp_init_attr *init_attr, | |
| 617 | + u32 sq_ring_size) | |
| 617 | 618 | { |
| 618 | 619 | if (init_attr->cap.max_send_wr > dev->dev_attr.max_sq_depth) { |
| 619 | 620 | ibdev_dbg(&dev->ibdev, |
| @@ -622,6 +623,14 @@ static int efa_qp_validate_cap(struct efa_dev *dev, · 2 unmodified lines | ||
| 622 | 623 | dev->dev_attr.max_sq_depth); |
| 623 | 624 | return -EINVAL; |
| 624 | 625 | } |
| 626 | + | |
| 627 | + if (sq_ring_size > dev->dev_attr.max_llq_size) { | |
| 628 | + ibdev_dbg(&dev->ibdev, | |
| 629 | + "qp: requested sq ring size[%u] exceeds the max[%u]\n", | |
| 630 | + sq_ring_size, dev->dev_attr.max_llq_size); | |
| 631 | + return -EINVAL; | |
| 632 | + } | |
| 633 | + | |
| 625 | 634 | if (init_attr->cap.max_recv_wr > dev->dev_attr.max_rq_depth) { |
| 626 | 635 | ibdev_dbg(&dev->ibdev, |
| 627 | 636 | "qp: requested receive wr[%u] exceeds the max[%u]\n", |
| @@ -691,14 +700,6 @@ int efa_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr, · 63 unmodified lines | ||
| 691 | 700 | ucontext = rdma_udata_to_drv_context(udata, struct efa_ucontext, |
| 692 | 701 | ibucontext); |
| 693 | 702 | |
| 694 | − err = efa_qp_validate_cap(dev, init_attr); | |
| 695 | − if (err) | |
| 696 | − goto err_out; | |
| 697 | − | |
| 698 | − err = efa_qp_validate_attr(dev, init_attr); | |
| 699 | − if (err) | |
| 700 | − goto err_out; | |
| 701 | − | |
| 702 | 703 | err = ib_copy_validate_udata_in_cm(udata, cmd, driver_qp_type, 0); |
| 703 | 704 | if (err) |
| 704 | 705 | goto err_out; |
| @@ -720,6 +721,14 @@ int efa_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr, · 15 unmodified lines | ||
| 720 | 721 | goto err_out; |
| 721 | 722 | } |
| 722 | 723 | |
| 724 | + err = efa_qp_validate_cap(dev, init_attr, cmd.sq_ring_size); | |
| 725 | + if (err) | |
| 726 | + goto err_out; | |
| 727 | + | |
| 728 | + err = efa_qp_validate_attr(dev, init_attr); | |
| 729 | + if (err) | |
| 730 | + goto err_out; | |
| 731 | + | |
| 723 | 732 | create_qp_params.uarn = ucontext->uarn; |
| 724 | 733 | create_qp_params.pd = to_epd(ibqp->pd)->pdn; |
| 725 | 734 | |
| @@ -300,6 +300,10 @@ struct ib_mr *hns_roce_rereg_user_mr(struct ib_mr *ibmr, int flags, u64 start, · 299 unmodified lines | ||
| 300 | 300 | goto err_out; |
| 301 | 301 | } |
| 302 | 302 | |
| 303 | + ret = ib_umem_check_rereg(mr->pbl_mtr.umem, flags, mr_access_flags); | |
| 304 | + if (ret) | |
| 305 | + goto err_out; | |
| 306 | + | |
| 303 | 307 | mailbox = hns_roce_alloc_cmd_mailbox(hr_dev); |
| 304 | 308 | ret = PTR_ERR_OR_ZERO(mailbox); |
| 305 | 309 | if (ret) |
| @@ -3803,6 +3803,10 @@ static struct ib_mr *irdma_rereg_user_mr(struct ib_mr *ib_mr, int flags, · 3802 unmodified lines | ||
| 3803 | 3803 | if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS)) |
| 3804 | 3804 | return ERR_PTR(-EOPNOTSUPP); |
| 3805 | 3805 | |
| 3806 | + ret = ib_umem_check_rereg(iwmr->region, flags, new_access); | |
| 3807 | + if (ret) | |
| 3808 | + return ERR_PTR(ret); | |
| 3809 | + | |
| 3806 | 3810 | if (dmabuf_revocable) { |
| 3807 | 3811 | umem_dmabuf = to_ib_umem_dmabuf(iwmr->region); |
| 3808 | 3812 | |
| @@ -209,6 +209,10 @@ struct ib_mr *mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags, u64 start, · 208 unmodified lines | ||
| 209 | 209 | struct mlx4_mpt_entry **pmpt_entry = &mpt_entry; |
| 210 | 210 | int err; |
| 211 | 211 | |
| 212 | + err = ib_umem_check_rereg(mmr->umem, flags, mr_access_flags); | |
| 213 | + if (err) | |
| 214 | + return ERR_PTR(err); | |
| 215 | + | |
| 212 | 216 | /* Since we synchronize this call and mlx4_ib_dereg_mr via uverbs, |
| 213 | 217 | * we assume that the calls can't run concurrently. Otherwise, a |
| 214 | 218 | * race exists. |
| @@ -1179,6 +1179,10 @@ struct ib_mr *mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start, · 1178 unmodified lines | ||
| 1179 | 1179 | if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS)) |
| 1180 | 1180 | return ERR_PTR(-EOPNOTSUPP); |
| 1181 | 1181 | |
| 1182 | + err = ib_umem_check_rereg(mr->umem, flags, new_access_flags); | |
| 1183 | + if (err) | |
| 1184 | + return ERR_PTR(err); | |
| 1185 | + | |
| 1182 | 1186 | if (!(flags & IB_MR_REREG_ACCESS)) |
| 1183 | 1187 | new_access_flags = mr->access_flags; |
| 1184 | 1188 | if (!(flags & IB_MR_REREG_PD)) |
| @@ -1319,6 +1319,7 @@ static struct ib_mr *rxe_rereg_user_mr(struct ib_mr *ibmr, int flags, · 1318 unmodified lines | ||
| 1319 | 1319 | struct rxe_mr *mr = to_rmr(ibmr); |
| 1320 | 1320 | struct rxe_pd *old_pd = to_rpd(ibmr->pd); |
| 1321 | 1321 | struct rxe_pd *pd = to_rpd(ibpd); |
| 1322 | + int err; | |
| 1322 | 1323 | |
| 1323 | 1324 | /* for now only support the two easy cases: |
| 1324 | 1325 | * rereg_pd and rereg_access |
| @@ -1328,6 +1329,10 @@ static struct ib_mr *rxe_rereg_user_mr(struct ib_mr *ibmr, int flags, · 3 unmodified lines | ||
| 1328 | 1329 | return ERR_PTR(-EOPNOTSUPP); |
| 1329 | 1330 | } |
| 1330 | 1331 | |
| 1332 | + err = ib_umem_check_rereg(mr->umem, flags, access); | |
| 1333 | + if (err) | |
| 1334 | + return ERR_PTR(err); | |
| 1335 | + | |
| 1331 | 1336 | if (flags & IB_MR_REREG_PD) { |
| 1332 | 1337 | rxe_put(old_pd); |
| 1333 | 1338 | rxe_get(pd); |
| @@ -1383,6 +1383,12 @@ isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc) · 1382 unmodified lines | ||
| 1383 | 1383 | ib_dma_sync_single_for_cpu(ib_dev, isert_conn->login_desc->dma_addr, |
| 1384 | 1384 | ISER_RX_SIZE, DMA_FROM_DEVICE); |
| 1385 | 1385 | |
| 1386 | + if (unlikely(wc->byte_len < ISER_HEADERS_LEN)) { | |
| 1387 | + isert_dbg("login request length %u is too short\n", | |
| 1388 | + wc->byte_len); | |
| 1389 | + return; | |
| 1390 | + } | |
| 1391 | + | |
| 1386 | 1392 | isert_conn->login_req_len = wc->byte_len - ISER_HEADERS_LEN; |
| 1387 | 1393 | |
| 1388 | 1394 | if (isert_conn->conn) { |
| @@ -1932,7 +1932,8 @@ static int srp_post_recv(struct srp_rdma_ch *ch, struct srp_iu *iu) · 1931 unmodified lines | ||
| 1932 | 1932 | return ib_post_recv(ch->qp, &wr, NULL); |
| 1933 | 1933 | } |
| 1934 | 1934 | |
| 1935 | −static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp) | |
| 1935 | +static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp, | |
| 1936 | + u32 byte_len) | |
| 1936 | 1937 | { |
| 1937 | 1938 | struct srp_target_port *target = ch->target; |
| 1938 | 1939 | struct srp_request *req; |
| @@ -1973,10 +1974,27 @@ static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp) · 34 unmodified lines | ||
| 1973 | 1974 | scmnd->result = rsp->status; |
| 1974 | 1975 | |
| 1975 | 1976 | if (rsp->flags & SRP_RSP_FLAG_SNSVALID) { |
| 1976 | − memcpy(scmnd->sense_buffer, rsp->data + | |
| 1977 | − be32_to_cpu(rsp->resp_data_len), | |
| 1978 | − min_t(int, be32_to_cpu(rsp->sense_data_len), | |
| 1979 | − SCSI_SENSE_BUFFERSIZE)); | |
| 1977 | + u32 resp_len = be32_to_cpu(rsp->resp_data_len); | |
| 1978 | + u32 sense_len = be32_to_cpu(rsp->sense_data_len); | |
| 1979 | + | |
| 1980 | + /* | |
| 1981 | + * The sense data starts resp_data_len bytes past the | |
| 1982 | + * response data area; both lengths come from the | |
| 1983 | + * target-controlled response. Copy the sense data | |
| 1984 | + * only if it has not been truncated, that is, only if | |
| 1985 | + * the full sense region fits within the bytes actually | |
| 1986 | + * received. Otherwise the copy source would run past | |
| 1987 | + * the receive buffer (sized to the target-chosen | |
| 1988 | + * max_ti_iu_len), reading out of bounds. | |
| 1989 | + */ | |
| 1990 | + if (sizeof(*rsp) + (u64)resp_len + sense_len <= byte_len) | |
| 1991 | + memcpy(scmnd->sense_buffer, | |
| 1992 | + rsp->data + resp_len, | |
| 1993 | + min(sense_len, SCSI_SENSE_BUFFERSIZE)); | |
| 1994 | + else | |
| 1995 | + shost_printk(KERN_ERR, target->scsi_host, | |
| 1996 | + "dropping truncated sense data (resp_data_len %u sense_data_len %u, %u bytes received)\n", | |
| 1997 | + resp_len, sense_len, byte_len); | |
| 1980 | 1998 | } |
| 1981 | 1999 | |
| 1982 | 2000 | if (unlikely(rsp->flags & SRP_RSP_FLAG_DIUNDER)) |
| @@ -2086,7 +2104,7 @@ static void srp_recv_done(struct ib_cq *cq, struct ib_wc *wc) · 103 unmodified lines | ||
| 2086 | 2104 | |
| 2087 | 2105 | switch (opcode) { |
| 2088 | 2106 | case SRP_RSP: |
| 2089 | − srp_process_rsp(ch, iu->buf); | |
| 2107 | + srp_process_rsp(ch, iu->buf, wc->byte_len); | |
| 2090 | 2108 | break; |
| 2091 | 2109 | |
| 2092 | 2110 | case SRP_CRED_REQ: |
| @@ -156,6 +156,8 @@ void ib_umem_dmabuf_revoke_lock(struct ib_umem_dmabuf *umem_dmabuf); · 155 unmodified lines | ||
| 156 | 156 | void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf); |
| 157 | 157 | void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf); |
| 158 | 158 | |
| 159 | +int ib_umem_check_rereg(struct ib_umem *umem, int flags, int new_access_flags); | |
| 160 | + | |
| 159 | 161 | #else /* CONFIG_INFINIBAND_USER_MEM */ |
| 160 | 162 | |
| 161 | 163 | #include <linux/err.h> |
| @@ -230,5 +232,11 @@ static inline void ib_umem_dmabuf_revoke_lock(struct ib_umem_dmabuf *umem_dmabuf · 68 unmodified lines | ||
| 230 | 232 | static inline void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf) {} |
| 231 | 233 | static inline void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf) {} |
| 232 | 234 | |
| 235 | +static inline int ib_umem_check_rereg(struct ib_umem *umem, int flags, | |
| 236 | + int new_access_flags) | |
| 237 | +{ | |
| 238 | + return -EOPNOTSUPP; | |
| 239 | +} | |
| 240 | + | |
| 233 | 241 | #endif /* CONFIG_INFINIBAND_USER_MEM */ |
| 234 | 242 | #endif /* IB_UMEM_H */ |