Merge tag '9p-for-6.2-rc1' of https://github.com/martinetd/linux

Pull 9p updates from Dominique Martinet:

- improve p9_check_errors to check buffer size instead of msize when
possible (e.g. not zero-copy)

- some more syzbot and KCSAN fixes

- minor headers include cleanup

* tag '9p-for-6.2-rc1' of https://github.com/martinetd/linux:
9p/client: fix data race on req->status
net/9p: fix response size check in p9_check_errors()
net/9p: distinguish zero-copy requests
9p/xen: do not memcpy header into req->rc
9p: set req refcount to zero to avoid uninitialized usage
9p/net: Remove unneeded idr.h #include
9p/fs: Remove unneeded idr.h #include

+42 -38
-1
fs/9p/fid.c
··· 11 11 #include <linux/fs.h> 12 12 #include <linux/slab.h> 13 13 #include <linux/sched.h> 14 - #include <linux/idr.h> 15 14 #include <net/9p/9p.h> 16 15 #include <net/9p/client.h> 17 16
-1
fs/9p/v9fs.c
··· 14 14 #include <linux/sched.h> 15 15 #include <linux/cred.h> 16 16 #include <linux/parser.h> 17 - #include <linux/idr.h> 18 17 #include <linux/slab.h> 19 18 #include <linux/seq_file.h> 20 19 #include <net/9p/9p.h>
-1
fs/9p/vfs_addr.c
··· 14 14 #include <linux/string.h> 15 15 #include <linux/inet.h> 16 16 #include <linux/pagemap.h> 17 - #include <linux/idr.h> 18 17 #include <linux/sched.h> 19 18 #include <linux/swap.h> 20 19 #include <linux/uio.h>
-1
fs/9p/vfs_dentry.c
··· 15 15 #include <linux/string.h> 16 16 #include <linux/inet.h> 17 17 #include <linux/namei.h> 18 - #include <linux/idr.h> 19 18 #include <linux/sched.h> 20 19 #include <linux/slab.h> 21 20 #include <net/9p/9p.h>
-1
fs/9p/vfs_dir.c
··· 14 14 #include <linux/string.h> 15 15 #include <linux/sched.h> 16 16 #include <linux/inet.h> 17 - #include <linux/idr.h> 18 17 #include <linux/slab.h> 19 18 #include <linux/uio.h> 20 19 #include <linux/fscache.h>
-1
fs/9p/vfs_file.c
··· 18 18 #include <linux/pagemap.h> 19 19 #include <linux/utsname.h> 20 20 #include <linux/uaccess.h> 21 - #include <linux/idr.h> 22 21 #include <linux/uio.h> 23 22 #include <linux/slab.h> 24 23 #include <net/9p/9p.h>
-1
fs/9p/vfs_inode.c
··· 17 17 #include <linux/string.h> 18 18 #include <linux/inet.h> 19 19 #include <linux/namei.h> 20 - #include <linux/idr.h> 21 20 #include <linux/sched.h> 22 21 #include <linux/slab.h> 23 22 #include <linux/xattr.h>
-1
fs/9p/vfs_inode_dotl.c
··· 15 15 #include <linux/string.h> 16 16 #include <linux/inet.h> 17 17 #include <linux/namei.h> 18 - #include <linux/idr.h> 19 18 #include <linux/sched.h> 20 19 #include <linux/slab.h> 21 20 #include <linux/xattr.h>
-1
fs/9p/vfs_super.c
··· 15 15 #include <linux/inet.h> 16 16 #include <linux/pagemap.h> 17 17 #include <linux/mount.h> 18 - #include <linux/idr.h> 19 18 #include <linux/sched.h> 20 19 #include <linux/slab.h> 21 20 #include <linux/statfs.h>
+2
include/net/9p/9p.h
··· 531 531 * @offset: used by marshalling routines to track current position in buffer 532 532 * @capacity: used by marshalling routines to track total malloc'd capacity 533 533 * @sdata: payload 534 + * @zc: whether zero-copy is used 534 535 * 535 536 * &p9_fcall represents the structure for all 9P RPC 536 537 * transactions. Requests are packaged into fcalls, and reponses ··· 550 549 551 550 struct kmem_cache *cache; 552 551 u8 *sdata; 552 + bool zc; 553 553 }; 554 554 555 555 int p9_errstr2errno(char *errstr, int len);
+22 -11
net/9p/client.c
··· 297 297 p9pdu_reset(&req->rc); 298 298 req->t_err = 0; 299 299 req->status = REQ_STATUS_ALLOC; 300 + /* refcount needs to be set to 0 before inserting into the idr 301 + * so p9_tag_lookup does not accept a request that is not fully 302 + * initialized. refcount_set to 2 below will mark request ready. 303 + */ 304 + refcount_set(&req->refcount, 0); 300 305 init_waitqueue_head(&req->wq); 301 306 INIT_LIST_HEAD(&req->req_list); 302 307 ··· 443 438 * the status change is visible to another thread 444 439 */ 445 440 smp_wmb(); 446 - req->status = status; 441 + WRITE_ONCE(req->status, status); 447 442 448 443 wake_up(&req->wq); 449 444 p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc.tag); ··· 519 514 int ecode; 520 515 521 516 err = p9_parse_header(&req->rc, NULL, &type, NULL, 0); 522 - if (req->rc.size >= c->msize) { 523 - p9_debug(P9_DEBUG_ERROR, 524 - "requested packet size too big: %d\n", 525 - req->rc.size); 517 + if (req->rc.size > req->rc.capacity && !req->rc.zc) { 518 + pr_err("requested packet size too big: %d does not fit %zu (type=%d)\n", 519 + req->rc.size, req->rc.capacity, req->rc.id); 526 520 return -EIO; 527 521 } 528 522 /* dump the response from server ··· 604 600 /* if we haven't received a response for oldreq, 605 601 * remove it from the list 606 602 */ 607 - if (oldreq->status == REQ_STATUS_SENT) { 603 + if (READ_ONCE(oldreq->status) == REQ_STATUS_SENT) { 608 604 if (c->trans_mod->cancelled) 609 605 c->trans_mod->cancelled(c, oldreq); 610 606 } ··· 684 680 if (IS_ERR(req)) 685 681 return req; 686 682 683 + req->tc.zc = false; 684 + req->rc.zc = false; 685 + 687 686 if (signal_pending(current)) { 688 687 sigpending = 1; 689 688 clear_thread_flag(TIF_SIGPENDING); ··· 704 697 } 705 698 again: 706 699 /* Wait for the response */ 707 - err = wait_event_killable(req->wq, req->status >= REQ_STATUS_RCVD); 700 + err = wait_event_killable(req->wq, 701 + READ_ONCE(req->status) >= REQ_STATUS_RCVD); 708 702 709 703 /* Make sure our req is coherent with regard to updates in other 710 704 * threads - echoes to wmb() in the callback ··· 719 711 goto again; 720 712 } 721 713 722 - if (req->status == REQ_STATUS_ERROR) { 714 + if (READ_ONCE(req->status) == REQ_STATUS_ERROR) { 723 715 p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); 724 716 err = req->t_err; 725 717 } ··· 732 724 p9_client_flush(c, req); 733 725 734 726 /* if we received the response anyway, don't signal error */ 735 - if (req->status == REQ_STATUS_RCVD) 727 + if (READ_ONCE(req->status) == REQ_STATUS_RCVD) 736 728 err = 0; 737 729 } 738 730 recalc_sigpending: ··· 786 778 if (IS_ERR(req)) 787 779 return req; 788 780 781 + req->tc.zc = true; 782 + req->rc.zc = true; 783 + 789 784 if (signal_pending(current)) { 790 785 sigpending = 1; 791 786 clear_thread_flag(TIF_SIGPENDING); ··· 804 793 if (err != -ERESTARTSYS) 805 794 goto recalc_sigpending; 806 795 } 807 - if (req->status == REQ_STATUS_ERROR) { 796 + if (READ_ONCE(req->status) == REQ_STATUS_ERROR) { 808 797 p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); 809 798 err = req->t_err; 810 799 } ··· 817 806 p9_client_flush(c, req); 818 807 819 808 /* if we received the response anyway, don't signal error */ 820 - if (req->status == REQ_STATUS_RCVD) 809 + if (READ_ONCE(req->status) == REQ_STATUS_RCVD) 821 810 err = 0; 822 811 } 823 812 recalc_sigpending:
+6 -7
net/9p/trans_fd.c
··· 20 20 #include <linux/un.h> 21 21 #include <linux/uaccess.h> 22 22 #include <linux/inet.h> 23 - #include <linux/idr.h> 24 23 #include <linux/file.h> 25 24 #include <linux/parser.h> 26 25 #include <linux/slab.h> ··· 201 202 202 203 list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { 203 204 list_move(&req->req_list, &cancel_list); 204 - req->status = REQ_STATUS_ERROR; 205 + WRITE_ONCE(req->status, REQ_STATUS_ERROR); 205 206 } 206 207 list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) { 207 208 list_move(&req->req_list, &cancel_list); 208 - req->status = REQ_STATUS_ERROR; 209 + WRITE_ONCE(req->status, REQ_STATUS_ERROR); 209 210 } 210 211 211 212 spin_unlock(&m->req_lock); ··· 466 467 467 468 req = list_entry(m->unsent_req_list.next, struct p9_req_t, 468 469 req_list); 469 - req->status = REQ_STATUS_SENT; 470 + WRITE_ONCE(req->status, REQ_STATUS_SENT); 470 471 p9_debug(P9_DEBUG_TRANS, "move req %p\n", req); 471 472 list_move_tail(&req->req_list, &m->req_list); 472 473 ··· 675 676 return m->err; 676 677 677 678 spin_lock(&m->req_lock); 678 - req->status = REQ_STATUS_UNSENT; 679 + WRITE_ONCE(req->status, REQ_STATUS_UNSENT); 679 680 list_add_tail(&req->req_list, &m->unsent_req_list); 680 681 spin_unlock(&m->req_lock); 681 682 ··· 702 703 703 704 if (req->status == REQ_STATUS_UNSENT) { 704 705 list_del(&req->req_list); 705 - req->status = REQ_STATUS_FLSHD; 706 + WRITE_ONCE(req->status, REQ_STATUS_FLSHD); 706 707 p9_req_put(client, req); 707 708 ret = 0; 708 709 } ··· 731 732 * remove it from the list. 732 733 */ 733 734 list_del(&req->req_list); 734 - req->status = REQ_STATUS_FLSHD; 735 + WRITE_ONCE(req->status, REQ_STATUS_FLSHD); 735 736 spin_unlock(&m->req_lock); 736 737 737 738 p9_req_put(client, req);
+2 -3
net/9p/trans_rdma.c
··· 21 21 #include <linux/un.h> 22 22 #include <linux/uaccess.h> 23 23 #include <linux/inet.h> 24 - #include <linux/idr.h> 25 24 #include <linux/file.h> 26 25 #include <linux/parser.h> 27 26 #include <linux/semaphore.h> ··· 506 507 * because doing if after could erase the REQ_STATUS_RCVD 507 508 * status in case of a very fast reply. 508 509 */ 509 - req->status = REQ_STATUS_SENT; 510 + WRITE_ONCE(req->status, REQ_STATUS_SENT); 510 511 err = ib_post_send(rdma->qp, &wr, NULL); 511 512 if (err) 512 513 goto send_error; ··· 516 517 517 518 /* Handle errors that happened during or while preparing the send: */ 518 519 send_error: 519 - req->status = REQ_STATUS_ERROR; 520 + WRITE_ONCE(req->status, REQ_STATUS_ERROR); 520 521 kfree(c); 521 522 p9_debug(P9_DEBUG_ERROR, "Error %d in rdma_request()\n", err); 522 523
+5 -5
net/9p/trans_virtio.c
··· 22 22 #include <linux/un.h> 23 23 #include <linux/uaccess.h> 24 24 #include <linux/inet.h> 25 - #include <linux/idr.h> 26 25 #include <linux/file.h> 27 26 #include <linux/highmem.h> 28 27 #include <linux/slab.h> ··· 262 263 263 264 p9_debug(P9_DEBUG_TRANS, "9p debug: virtio request\n"); 264 265 265 - req->status = REQ_STATUS_SENT; 266 + WRITE_ONCE(req->status, REQ_STATUS_SENT); 266 267 req_retry: 267 268 spin_lock_irqsave(&chan->lock, flags); 268 269 ··· 468 469 inlen = n; 469 470 } 470 471 } 471 - req->status = REQ_STATUS_SENT; 472 + WRITE_ONCE(req->status, REQ_STATUS_SENT); 472 473 req_retry_pinned: 473 474 spin_lock_irqsave(&chan->lock, flags); 474 475 ··· 531 532 spin_unlock_irqrestore(&chan->lock, flags); 532 533 kicked = 1; 533 534 p9_debug(P9_DEBUG_TRANS, "virtio request kicked\n"); 534 - err = wait_event_killable(req->wq, req->status >= REQ_STATUS_RCVD); 535 + err = wait_event_killable(req->wq, 536 + READ_ONCE(req->status) >= REQ_STATUS_RCVD); 535 537 // RERROR needs reply (== error string) in static data 536 - if (req->status == REQ_STATUS_RCVD && 538 + if (READ_ONCE(req->status) == REQ_STATUS_RCVD && 537 539 unlikely(req->rc.sdata[4] == P9_RERROR)) 538 540 handle_rerror(req, in_hdr_len, offs, in_pages); 539 541
+5 -3
net/9p/trans_xen.c
··· 157 157 &masked_prod, masked_cons, 158 158 XEN_9PFS_RING_SIZE(ring)); 159 159 160 - p9_req->status = REQ_STATUS_SENT; 160 + WRITE_ONCE(p9_req->status, REQ_STATUS_SENT); 161 161 virt_wmb(); /* write ring before updating pointer */ 162 162 prod += size; 163 163 ring->intf->out_prod = prod; ··· 212 212 dev_warn(&priv->dev->dev, 213 213 "requested packet size too big: %d for tag %d with capacity %zd\n", 214 214 h.size, h.tag, req->rc.capacity); 215 - req->status = REQ_STATUS_ERROR; 215 + WRITE_ONCE(req->status, REQ_STATUS_ERROR); 216 216 goto recv_error; 217 217 } 218 218 219 - memcpy(&req->rc, &h, sizeof(h)); 219 + req->rc.size = h.size; 220 + req->rc.id = h.id; 221 + req->rc.tag = h.tag; 220 222 req->rc.offset = 0; 221 223 222 224 masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE(ring));