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 | bool __rdma_block_iter_next(struct ib_block_iter *biter) | 20 | bool __rdma_block_iter_next(struct ib_block_iter *biter) |
| 21 | { | 21 | { |
| 22 | unsigned int block_offset; | 22 | dma_addr_t block_offset; |
| 23 | unsigned int delta; | 23 | dma_addr_t delta; |
| 24 | 24 | ||
| 25 | if (!biter->__sg_nents || !biter->__sg) | 25 | if (!biter->__sg_nents || !biter->__sg) |
| 26 | return false; | 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 | static int get_devt_from_fd(unsigned int fd, dev_t *ret_dev) | 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); | 87 | if (fd_empty(f) || fd_file(f)->f_op != &ucaps_cdev_fops) |
| 88 | if (!file) | ||
| 89 | return -EBADF; | 88 | return -EBADF; |
| 90 | 89 | ||
| 91 | *ret_dev = file_inode(file)->i_rdev; | 90 | *ret_dev = file_inode(fd_file(f))->i_rdev; |
| 92 | fput(file); | ||
| 93 | return 0; | 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 | return 0; | 332 | return 0; |
| 333 | } | 333 | } |
| 334 | EXPORT_SYMBOL(ib_umem_copy_from); | 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 | if (ret) | 47 | if (ret) |
| 48 | goto err; | 48 | goto err; |
| 49 | 49 | ||
| 50 | if (dmah->cpu_id >= nr_cpu_ids) { | ||
| 51 | ret = -EINVAL; | ||
| 52 | goto err; | ||
| 53 | } | ||
| 54 | |||
| 50 | if (!cpumask_test_cpu(dmah->cpu_id, current->cpus_ptr)) { | 55 | if (!cpumask_test_cpu(dmah->cpu_id, current->cpus_ptr)) { |
| 51 | ret = -EPERM; | 56 | ret = -EPERM; |
| 52 | goto err; | 57 | goto err; |
| @@ -613,7 +613,8 @@ err_remove_mmap: · 612 unmodified lines | |||
| 613 | } | 613 | } |
| 614 | 614 | ||
| 615 | static int efa_qp_validate_cap(struct efa_dev *dev, | 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 | if (init_attr->cap.max_send_wr > dev->dev_attr.max_sq_depth) { | 619 | if (init_attr->cap.max_send_wr > dev->dev_attr.max_sq_depth) { |
| 619 | ibdev_dbg(&dev->ibdev, | 620 | ibdev_dbg(&dev->ibdev, |
| @@ -622,6 +623,14 @@ static int efa_qp_validate_cap(struct efa_dev *dev, · 2 unmodified lines | |||
| 622 | dev->dev_attr.max_sq_depth); | 623 | dev->dev_attr.max_sq_depth); |
| 623 | return -EINVAL; | 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 | if (init_attr->cap.max_recv_wr > dev->dev_attr.max_rq_depth) { | 634 | if (init_attr->cap.max_recv_wr > dev->dev_attr.max_rq_depth) { |
| 626 | ibdev_dbg(&dev->ibdev, | 635 | ibdev_dbg(&dev->ibdev, |
| 627 | "qp: requested receive wr[%u] exceeds the max[%u]\n", | 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 | ucontext = rdma_udata_to_drv_context(udata, struct efa_ucontext, | 700 | ucontext = rdma_udata_to_drv_context(udata, struct efa_ucontext, |
| 692 | ibucontext); | 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 | err = ib_copy_validate_udata_in_cm(udata, cmd, driver_qp_type, 0); | 703 | err = ib_copy_validate_udata_in_cm(udata, cmd, driver_qp_type, 0); |
| 703 | if (err) | 704 | if (err) |
| 704 | goto err_out; | 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 | goto err_out; | 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 | create_qp_params.uarn = ucontext->uarn; | 732 | create_qp_params.uarn = ucontext->uarn; |
| 724 | create_qp_params.pd = to_epd(ibqp->pd)->pdn; | 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 | goto err_out; | 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 | mailbox = hns_roce_alloc_cmd_mailbox(hr_dev); | 307 | mailbox = hns_roce_alloc_cmd_mailbox(hr_dev); |
| 304 | ret = PTR_ERR_OR_ZERO(mailbox); | 308 | ret = PTR_ERR_OR_ZERO(mailbox); |
| 305 | if (ret) | 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 | if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS)) | 3803 | if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS)) |
| 3804 | return ERR_PTR(-EOPNOTSUPP); | 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 | if (dmabuf_revocable) { | 3810 | if (dmabuf_revocable) { |
| 3807 | umem_dmabuf = to_ib_umem_dmabuf(iwmr->region); | 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 | struct mlx4_mpt_entry **pmpt_entry = &mpt_entry; | 209 | struct mlx4_mpt_entry **pmpt_entry = &mpt_entry; |
| 210 | int err; | 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 | /* Since we synchronize this call and mlx4_ib_dereg_mr via uverbs, | 216 | /* Since we synchronize this call and mlx4_ib_dereg_mr via uverbs, |
| 213 | * we assume that the calls can't run concurrently. Otherwise, a | 217 | * we assume that the calls can't run concurrently. Otherwise, a |
| 214 | * race exists. | 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 | if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS)) | 1179 | if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS)) |
| 1180 | return ERR_PTR(-EOPNOTSUPP); | 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 | if (!(flags & IB_MR_REREG_ACCESS)) | 1186 | if (!(flags & IB_MR_REREG_ACCESS)) |
| 1183 | new_access_flags = mr->access_flags; | 1187 | new_access_flags = mr->access_flags; |
| 1184 | if (!(flags & IB_MR_REREG_PD)) | 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 | struct rxe_mr *mr = to_rmr(ibmr); | 1319 | struct rxe_mr *mr = to_rmr(ibmr); |
| 1320 | struct rxe_pd *old_pd = to_rpd(ibmr->pd); | 1320 | struct rxe_pd *old_pd = to_rpd(ibmr->pd); |
| 1321 | struct rxe_pd *pd = to_rpd(ibpd); | 1321 | struct rxe_pd *pd = to_rpd(ibpd); |
| 1322 | int err; | ||
| 1322 | 1323 | ||
| 1323 | /* for now only support the two easy cases: | 1324 | /* for now only support the two easy cases: |
| 1324 | * rereg_pd and rereg_access | 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 | return ERR_PTR(-EOPNOTSUPP); | 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 | if (flags & IB_MR_REREG_PD) { | 1336 | if (flags & IB_MR_REREG_PD) { |
| 1332 | rxe_put(old_pd); | 1337 | rxe_put(old_pd); |
| 1333 | rxe_get(pd); | 1338 | rxe_get(pd); |
| @@ -1383,6 +1383,12 @@ isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc) · 1382 unmodified lines | |||
| 1383 | ib_dma_sync_single_for_cpu(ib_dev, isert_conn->login_desc->dma_addr, | 1383 | ib_dma_sync_single_for_cpu(ib_dev, isert_conn->login_desc->dma_addr, |
| 1384 | ISER_RX_SIZE, DMA_FROM_DEVICE); | 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 | isert_conn->login_req_len = wc->byte_len - ISER_HEADERS_LEN; | 1392 | isert_conn->login_req_len = wc->byte_len - ISER_HEADERS_LEN; |
| 1387 | 1393 | ||
| 1388 | if (isert_conn->conn) { | 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 | return ib_post_recv(ch->qp, &wr, NULL); | 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 | struct srp_target_port *target = ch->target; | 1938 | struct srp_target_port *target = ch->target; |
| 1938 | struct srp_request *req; | 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 | scmnd->result = rsp->status; | 1974 | scmnd->result = rsp->status; |
| 1974 | 1975 | ||
| 1975 | if (rsp->flags & SRP_RSP_FLAG_SNSVALID) { | 1976 | if (rsp->flags & SRP_RSP_FLAG_SNSVALID) { |
| 1976 | memcpy(scmnd->sense_buffer, rsp->data + | 1977 | u32 resp_len = be32_to_cpu(rsp->resp_data_len); |
| 1977 | be32_to_cpu(rsp->resp_data_len), | 1978 | u32 sense_len = be32_to_cpu(rsp->sense_data_len); |
| 1978 | min_t(int, be32_to_cpu(rsp->sense_data_len), | 1979 | |
| 1979 | SCSI_SENSE_BUFFERSIZE)); | 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 | if (unlikely(rsp->flags & SRP_RSP_FLAG_DIUNDER)) | 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 | switch (opcode) { | 2105 | switch (opcode) { |
| 2088 | case SRP_RSP: | 2106 | case SRP_RSP: |
| 2089 | srp_process_rsp(ch, iu->buf); | 2107 | srp_process_rsp(ch, iu->buf, wc->byte_len); |
| 2090 | break; | 2108 | break; |
| 2091 | 2109 | ||
| 2092 | case SRP_CRED_REQ: | 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 | void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf); | 156 | void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf); |
| 157 | void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf); | 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 | #else /* CONFIG_INFINIBAND_USER_MEM */ | 161 | #else /* CONFIG_INFINIBAND_USER_MEM */ |
| 160 | 162 | ||
| 161 | #include <linux/err.h> | 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 | static inline void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf) {} | 232 | static inline void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf) {} |
| 231 | static inline void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf) {} | 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 | #endif /* CONFIG_INFINIBAND_USER_MEM */ | 241 | #endif /* CONFIG_INFINIBAND_USER_MEM */ |
| 234 | #endif /* IB_UMEM_H */ | 242 | #endif /* IB_UMEM_H */ |