Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

Pull 9p updates from Dominique Martinet:
"A bunch of unrelated fixes:

- polling fix for trans fd that ought to have been fixed otherwise
back in March, but apparently came back somewhere else...

- USB transport buffer overflow fix

- Some dentry lifetime rework to handle metadata update for currently
opened files in uncached mode, or inode type change in cached mode

- a double-put on invalid flush found by syzbot

- and finally /sys/fs/9p/caches not advancing buffer and overwriting
itself for large contents

Thanks to everyone involved!"

* tag '9p-for-6.18-rc1' of https://github.com/martinetd/linux:
9p: sysfs_init: don't hardcode error to ENOMEM
9p: fix /sys/fs/9p/caches overwriting itself
9p: clean up comment typos
9p/trans_fd: p9_fd_request: kick rx thread if EPOLLIN
net/9p: fix double req put in p9_fd_cancelled
net/9p: Fix buffer overflow in USB transport layer
fs/9p: Add p9_debug(VFS) in d_revalidate
fs/9p: Invalidate dentry if inode type change detected in cached mode
fs/9p: Refresh metadata in d_revalidate for uncached mode too

+70 -28
+9 -7
fs/9p/v9fs.c
··· 438 438 v9ses->flags &= ~V9FS_ACCESS_MASK; 439 439 v9ses->flags |= V9FS_ACCESS_USER; 440 440 } 441 - /*FIXME !! */ 442 - /* for legacy mode, fall back to V9FS_ACCESS_ANY */ 441 + /* FIXME: for legacy mode, fall back to V9FS_ACCESS_ANY */ 443 442 if (!(v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses)) && 444 443 ((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) { 445 444 ··· 449 450 if (!v9fs_proto_dotl(v9ses) || 450 451 !((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)) { 451 452 /* 452 - * We support ACL checks on clinet only if the protocol is 453 + * We support ACL checks on client only if the protocol is 453 454 * 9P2000.L and access is V9FS_ACCESS_CLIENT. 454 455 */ 455 456 v9ses->flags &= ~V9FS_ACL_MASK; ··· 560 561 spin_lock(&v9fs_sessionlist_lock); 561 562 list_for_each_entry(v9ses, &v9fs_sessionlist, slist) { 562 563 if (v9ses->cachetag) { 563 - n = snprintf(buf, limit, "%s\n", v9ses->cachetag); 564 + n = snprintf(buf + count, limit, "%s\n", v9ses->cachetag); 564 565 if (n < 0) { 565 566 count = n; 566 567 break; ··· 596 597 597 598 static int __init v9fs_sysfs_init(void) 598 599 { 600 + int ret; 601 + 599 602 v9fs_kobj = kobject_create_and_add("9p", fs_kobj); 600 603 if (!v9fs_kobj) 601 604 return -ENOMEM; 602 605 603 - if (sysfs_create_group(v9fs_kobj, &v9fs_attr_group)) { 606 + ret = sysfs_create_group(v9fs_kobj, &v9fs_attr_group); 607 + if (ret) { 604 608 kobject_put(v9fs_kobj); 605 - return -ENOMEM; 609 + return ret; 606 610 } 607 611 608 612 return 0; ··· 671 669 int err; 672 670 673 671 pr_info("Installing v9fs 9p2000 file system support\n"); 674 - /* TODO: Setup list of registered trasnport modules */ 672 + /* TODO: Setup list of registered transport modules */ 675 673 676 674 err = v9fs_init_inode_cache(); 677 675 if (err < 0) {
+29 -4
fs/9p/vfs_dentry.c
··· 66 66 struct p9_fid *fid; 67 67 struct inode *inode; 68 68 struct v9fs_inode *v9inode; 69 + unsigned int cached; 69 70 70 71 if (flags & LOOKUP_RCU) 71 72 return -ECHILD; ··· 76 75 goto out_valid; 77 76 78 77 v9inode = V9FS_I(inode); 79 - if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) { 78 + struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); 79 + 80 + cached = v9ses->cache & (CACHE_META | CACHE_LOOSE); 81 + 82 + if (!cached || v9inode->cache_validity & V9FS_INO_INVALID_ATTR) { 80 83 int retval; 81 84 struct v9fs_session_info *v9ses; 82 85 83 86 fid = v9fs_fid_lookup(dentry); 84 - if (IS_ERR(fid)) 87 + if (IS_ERR(fid)) { 88 + p9_debug( 89 + P9_DEBUG_VFS, 90 + "v9fs_fid_lookup: dentry = %pd (%p), got error %pe\n", 91 + dentry, dentry, fid); 85 92 return PTR_ERR(fid); 93 + } 86 94 87 95 v9ses = v9fs_inode2v9ses(inode); 88 96 if (v9fs_proto_dotl(v9ses)) ··· 100 90 retval = v9fs_refresh_inode(fid, inode); 101 91 p9_fid_put(fid); 102 92 103 - if (retval == -ENOENT) 93 + if (retval == -ENOENT) { 94 + p9_debug(P9_DEBUG_VFS, "dentry: %pd (%p) invalidated due to ENOENT\n", 95 + dentry, dentry); 104 96 return 0; 105 - if (retval < 0) 97 + } 98 + if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) { 99 + p9_debug(P9_DEBUG_VFS, "dentry: %pd (%p) invalidated due to type change\n", 100 + dentry, dentry); 101 + return 0; 102 + } 103 + if (retval < 0) { 104 + p9_debug(P9_DEBUG_VFS, 105 + "refresh inode: dentry = %pd (%p), got error %pe\n", 106 + dentry, dentry, ERR_PTR(retval)); 106 107 return retval; 108 + } 107 109 } 108 110 out_valid: 111 + p9_debug(P9_DEBUG_VFS, "dentry: %pd (%p) is valid\n", dentry, dentry); 109 112 return 1; 110 113 } 111 114 ··· 150 127 }; 151 128 152 129 const struct dentry_operations v9fs_dentry_operations = { 130 + .d_revalidate = v9fs_lookup_revalidate, 131 + .d_weak_revalidate = __v9fs_lookup_revalidate, 153 132 .d_release = v9fs_dentry_release, 154 133 .d_unalias_trylock = v9fs_dentry_unalias_trylock, 155 134 .d_unalias_unlock = v9fs_dentry_unalias_unlock,
+7 -1
fs/9p/vfs_inode.c
··· 1339 1339 * Don't update inode if the file type is different 1340 1340 */ 1341 1341 umode = p9mode2unixmode(v9ses, st, &rdev); 1342 - if (inode_wrong_type(inode, umode)) 1342 + if (inode_wrong_type(inode, umode)) { 1343 + /* 1344 + * Do this as a way of letting the caller know the inode should not 1345 + * be reused 1346 + */ 1347 + v9fs_invalidate_inode_attr(inode); 1343 1348 goto out; 1349 + } 1344 1350 1345 1351 /* 1346 1352 * We don't want to refresh inode->i_size,
+7 -1
fs/9p/vfs_inode_dotl.c
··· 897 897 /* 898 898 * Don't update inode if the file type is different 899 899 */ 900 - if (inode_wrong_type(inode, st->st_mode)) 900 + if (inode_wrong_type(inode, st->st_mode)) { 901 + /* 902 + * Do this as a way of letting the caller know the inode should not 903 + * be reused 904 + */ 905 + v9fs_invalidate_inode_attr(inode); 901 906 goto out; 907 + } 902 908 903 909 /* 904 910 * We don't want to refresh inode->i_size,
+5 -12
net/9p/trans_fd.c
··· 666 666 667 667 static int p9_fd_request(struct p9_client *client, struct p9_req_t *req) 668 668 { 669 - __poll_t n; 670 669 int err; 671 670 struct p9_trans_fd *ts = client->trans; 672 671 struct p9_conn *m = &ts->conn; ··· 685 686 list_add_tail(&req->req_list, &m->unsent_req_list); 686 687 spin_unlock(&m->req_lock); 687 688 688 - if (test_and_clear_bit(Wpending, &m->wsched)) 689 - n = EPOLLOUT; 690 - else 691 - n = p9_fd_poll(m->client, NULL, NULL); 692 - 693 - if (n & EPOLLOUT && !test_and_set_bit(Wworksched, &m->wsched)) 694 - schedule_work(&m->wq); 689 + p9_poll_mux(m); 695 690 696 691 return 0; 697 692 } ··· 719 726 p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req); 720 727 721 728 spin_lock(&m->req_lock); 722 - /* Ignore cancelled request if message has been received 723 - * before lock. 724 - */ 725 - if (req->status == REQ_STATUS_RCVD) { 729 + /* Ignore cancelled request if status changed since the request was 730 + * processed in p9_client_flush() 731 + */ 732 + if (req->status != REQ_STATUS_SENT) { 726 733 spin_unlock(&m->req_lock); 727 734 return 0; 728 735 }
+13 -3
net/9p/trans_usbg.c
··· 231 231 struct f_usb9pfs *usb9pfs = ep->driver_data; 232 232 struct usb_composite_dev *cdev = usb9pfs->function.config->cdev; 233 233 struct p9_req_t *p9_rx_req; 234 + unsigned int req_size = req->actual; 235 + int status = REQ_STATUS_RCVD; 234 236 235 237 if (req->status) { 236 238 dev_err(&cdev->gadget->dev, "%s usb9pfs complete --> %d, %d/%d\n", ··· 244 242 if (!p9_rx_req) 245 243 return; 246 244 247 - memcpy(p9_rx_req->rc.sdata, req->buf, req->actual); 245 + if (req_size > p9_rx_req->rc.capacity) { 246 + dev_err(&cdev->gadget->dev, 247 + "%s received data size %u exceeds buffer capacity %zu\n", 248 + ep->name, req_size, p9_rx_req->rc.capacity); 249 + req_size = 0; 250 + status = REQ_STATUS_ERROR; 251 + } 248 252 249 - p9_rx_req->rc.size = req->actual; 253 + memcpy(p9_rx_req->rc.sdata, req->buf, req_size); 250 254 251 - p9_client_cb(usb9pfs->client, p9_rx_req, REQ_STATUS_RCVD); 255 + p9_rx_req->rc.size = req_size; 256 + 257 + p9_client_cb(usb9pfs->client, p9_rx_req, status); 252 258 p9_req_put(usb9pfs->client, p9_rx_req); 253 259 254 260 complete(&usb9pfs->received);