Skip to content

Commit 80b7065

Browse files
committed
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
2 parents 18a7e21 + 528f218 commit 80b7065

File tree

6 files changed

+70
-28
lines changed

6 files changed

+70
-28
lines changed

fs/9p/v9fs.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -438,8 +438,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
438438
v9ses->flags &= ~V9FS_ACCESS_MASK;
439439
v9ses->flags |= V9FS_ACCESS_USER;
440440
}
441-
/*FIXME !! */
442-
/* for legacy mode, fall back to V9FS_ACCESS_ANY */
441+
/* FIXME: for legacy mode, fall back to V9FS_ACCESS_ANY */
443442
if (!(v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses)) &&
444443
((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) {
445444

@@ -450,7 +449,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
450449
if (!v9fs_proto_dotl(v9ses) ||
451450
!((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)) {
452451
/*
453-
* We support ACL checks on clinet only if the protocol is
452+
* We support ACL checks on client only if the protocol is
454453
* 9P2000.L and access is V9FS_ACCESS_CLIENT.
455454
*/
456455
v9ses->flags &= ~V9FS_ACL_MASK;
@@ -561,7 +560,7 @@ static ssize_t caches_show(struct kobject *kobj,
561560
spin_lock(&v9fs_sessionlist_lock);
562561
list_for_each_entry(v9ses, &v9fs_sessionlist, slist) {
563562
if (v9ses->cachetag) {
564-
n = snprintf(buf, limit, "%s\n", v9ses->cachetag);
563+
n = snprintf(buf + count, limit, "%s\n", v9ses->cachetag);
565564
if (n < 0) {
566565
count = n;
567566
break;
@@ -597,13 +596,16 @@ static const struct attribute_group v9fs_attr_group = {
597596

598597
static int __init v9fs_sysfs_init(void)
599598
{
599+
int ret;
600+
600601
v9fs_kobj = kobject_create_and_add("9p", fs_kobj);
601602
if (!v9fs_kobj)
602603
return -ENOMEM;
603604

604-
if (sysfs_create_group(v9fs_kobj, &v9fs_attr_group)) {
605+
ret = sysfs_create_group(v9fs_kobj, &v9fs_attr_group);
606+
if (ret) {
605607
kobject_put(v9fs_kobj);
606-
return -ENOMEM;
608+
return ret;
607609
}
608610

609611
return 0;
@@ -669,7 +671,7 @@ static int __init init_v9fs(void)
669671
int err;
670672

671673
pr_info("Installing v9fs 9p2000 file system support\n");
672-
/* TODO: Setup list of registered trasnport modules */
674+
/* TODO: Setup list of registered transport modules */
673675

674676
err = v9fs_init_inode_cache();
675677
if (err < 0) {

fs/9p/vfs_dentry.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
6666
struct p9_fid *fid;
6767
struct inode *inode;
6868
struct v9fs_inode *v9inode;
69+
unsigned int cached;
6970

7071
if (flags & LOOKUP_RCU)
7172
return -ECHILD;
@@ -75,13 +76,22 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
7576
goto out_valid;
7677

7778
v9inode = V9FS_I(inode);
78-
if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) {
79+
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
80+
81+
cached = v9ses->cache & (CACHE_META | CACHE_LOOSE);
82+
83+
if (!cached || v9inode->cache_validity & V9FS_INO_INVALID_ATTR) {
7984
int retval;
8085
struct v9fs_session_info *v9ses;
8186

8287
fid = v9fs_fid_lookup(dentry);
83-
if (IS_ERR(fid))
88+
if (IS_ERR(fid)) {
89+
p9_debug(
90+
P9_DEBUG_VFS,
91+
"v9fs_fid_lookup: dentry = %pd (%p), got error %pe\n",
92+
dentry, dentry, fid);
8493
return PTR_ERR(fid);
94+
}
8595

8696
v9ses = v9fs_inode2v9ses(inode);
8797
if (v9fs_proto_dotl(v9ses))
@@ -90,12 +100,25 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
90100
retval = v9fs_refresh_inode(fid, inode);
91101
p9_fid_put(fid);
92102

93-
if (retval == -ENOENT)
103+
if (retval == -ENOENT) {
104+
p9_debug(P9_DEBUG_VFS, "dentry: %pd (%p) invalidated due to ENOENT\n",
105+
dentry, dentry);
106+
return 0;
107+
}
108+
if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) {
109+
p9_debug(P9_DEBUG_VFS, "dentry: %pd (%p) invalidated due to type change\n",
110+
dentry, dentry);
94111
return 0;
95-
if (retval < 0)
112+
}
113+
if (retval < 0) {
114+
p9_debug(P9_DEBUG_VFS,
115+
"refresh inode: dentry = %pd (%p), got error %pe\n",
116+
dentry, dentry, ERR_PTR(retval));
96117
return retval;
118+
}
97119
}
98120
out_valid:
121+
p9_debug(P9_DEBUG_VFS, "dentry: %pd (%p) is valid\n", dentry, dentry);
99122
return 1;
100123
}
101124

@@ -127,6 +150,8 @@ const struct dentry_operations v9fs_cached_dentry_operations = {
127150
};
128151

129152
const struct dentry_operations v9fs_dentry_operations = {
153+
.d_revalidate = v9fs_lookup_revalidate,
154+
.d_weak_revalidate = __v9fs_lookup_revalidate,
130155
.d_release = v9fs_dentry_release,
131156
.d_unalias_trylock = v9fs_dentry_unalias_trylock,
132157
.d_unalias_unlock = v9fs_dentry_unalias_unlock,

fs/9p/vfs_inode.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1339,8 +1339,14 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
13391339
* Don't update inode if the file type is different
13401340
*/
13411341
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);
13431348
goto out;
1349+
}
13441350

13451351
/*
13461352
* We don't want to refresh inode->i_size,

fs/9p/vfs_inode_dotl.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -897,8 +897,14 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
897897
/*
898898
* Don't update inode if the file type is different
899899
*/
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);
901906
goto out;
907+
}
902908

903909
/*
904910
* We don't want to refresh inode->i_size,

net/9p/trans_fd.c

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,6 @@ static void p9_poll_mux(struct p9_conn *m)
666666

667667
static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
668668
{
669-
__poll_t n;
670669
int err;
671670
struct p9_trans_fd *ts = client->trans;
672671
struct p9_conn *m = &ts->conn;
@@ -686,13 +685,7 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
686685
list_add_tail(&req->req_list, &m->unsent_req_list);
687686
spin_unlock(&m->req_lock);
688687

689-
if (test_and_clear_bit(Wpending, &m->wsched))
690-
n = EPOLLOUT;
691-
else
692-
n = p9_fd_poll(m->client, NULL, NULL);
693-
694-
if (n & EPOLLOUT && !test_and_set_bit(Wworksched, &m->wsched))
695-
schedule_work(&m->wq);
688+
p9_poll_mux(m);
696689

697690
return 0;
698691
}
@@ -726,10 +719,10 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req)
726719
p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req);
727720

728721
spin_lock(&m->req_lock);
729-
/* Ignore cancelled request if message has been received
730-
* before lock.
731-
*/
732-
if (req->status == REQ_STATUS_RCVD) {
722+
/* Ignore cancelled request if status changed since the request was
723+
* processed in p9_client_flush()
724+
*/
725+
if (req->status != REQ_STATUS_SENT) {
733726
spin_unlock(&m->req_lock);
734727
return 0;
735728
}

net/9p/trans_usbg.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@ static void usb9pfs_rx_complete(struct usb_ep *ep, struct usb_request *req)
231231
struct f_usb9pfs *usb9pfs = ep->driver_data;
232232
struct usb_composite_dev *cdev = usb9pfs->function.config->cdev;
233233
struct p9_req_t *p9_rx_req;
234+
unsigned int req_size = req->actual;
235+
int status = REQ_STATUS_RCVD;
234236

235237
if (req->status) {
236238
dev_err(&cdev->gadget->dev, "%s usb9pfs complete --> %d, %d/%d\n",
@@ -242,11 +244,19 @@ static void usb9pfs_rx_complete(struct usb_ep *ep, struct usb_request *req)
242244
if (!p9_rx_req)
243245
return;
244246

245-
memcpy(p9_rx_req->rc.sdata, req->buf, req->actual);
247+
if (req_size > p9_rx_req->rc.capacity) {
248+
dev_err(&cdev->gadget->dev,
249+
"%s received data size %u exceeds buffer capacity %zu\n",
250+
ep->name, req_size, p9_rx_req->rc.capacity);
251+
req_size = 0;
252+
status = REQ_STATUS_ERROR;
253+
}
254+
255+
memcpy(p9_rx_req->rc.sdata, req->buf, req_size);
246256

247-
p9_rx_req->rc.size = req->actual;
257+
p9_rx_req->rc.size = req_size;
248258

249-
p9_client_cb(usb9pfs->client, p9_rx_req, REQ_STATUS_RCVD);
259+
p9_client_cb(usb9pfs->client, p9_rx_req, status);
250260
p9_req_put(usb9pfs->client, p9_rx_req);
251261

252262
complete(&usb9pfs->received);

0 commit comments

Comments
 (0)