Bunch of small fixes:

- three W=1 warning fixes: the NULL -> "" replacement isn't trivial
 but is serialized identically by the protocol layer and has been tested
 - one syzbot/KCSAN datarace annotation where we don't care about users
 messing with the fd they passed to mount -t 9p
 - removing a declaration without implementation
 - yet another race fix for trans_fd around connection close:
 the 'err' field is also used in potentially racy calls and this
 isn't complete, but it's better than what we have.
 - and finally a theorical memory leak fix on serialization failure
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE/IPbcYBuWt0zoYhOq06b7GqY5nAFAmVFmAcACgkQq06b7GqY
 5nASEg/9Fdtd9B//G+t/gQm0pdZIGoV+KbovWRrO4w3IIfENe8OP3A+8uZhmdij4
 p1tYUfyOPjMTxvZlmEArYjyiIkB5SsdYVMiOY6WfFRo3XEyMirdLDXa7beSnFLAs
 wuk5rAlndGIg+HwzXFD4WpKU5By5r6hnMgYeQ98bwB1bsF5ENZL+0VctFOd1H1zQ
 zwFChfsv4do3LfA2BssseTaH3PAniqs/X8gvDfslCL45YhitunzrB5C8pCOLpiA6
 j6+7iDBeh7H/S+xTG2h+NBdPh+emalex1GHckZHNaTyEWNGcnJnOG8qPy+ufNgyX
 G1Sxr80dX7oAXD74LqPfoG4IsgXsB/0sLnjFNxbfpcmGoka/GTWzV0O+9LauhN9X
 Nu3OnbOBM+VZR3VA7EpqCEbf5CAduQklWameZHGqqH8vr3wGJSPXs3eEpTnXnXmK
 yIUdFWvTL61Il/RSk1CFjlsxXh42tjNqlJobiOru3+zhmwFw3yffFnq3Mxn1Y+Mi
 4jet/E1VD7NB6nlTqRuaMWbWBC037pMgXfFe4BGbAynKLPbnBD8fjDKkbxoU66Qw
 ud5UabfuikR1ah5te8l1F956ij88HgKFuufQ6vqc98be3EqcIkXSe0/+fgXMcU55
 hPMmfLAP4g5p5VEi6kbOZdVAWqaE6EO1x6EzrQ+VCEg5hHJx0Ew=
 =ZD9A
 -----END PGP SIGNATURE-----

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

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

   - three W=1 warning fixes: the NULL -> "" replacement isn't trivial
     but is serialized identically by the protocol layer and has been
     tested

   - one syzbot/KCSAN datarace annotation where we don't care about
     users messing with the fd they passed to mount -t 9p

   - removing a declaration without implementation

   - yet another race fix for trans_fd around connection close: the
     'err' field is also used in potentially racy calls and this isn't
     complete, but it's better than what we had

   - and finally a theorical memory leak fix on serialization failure"

* tag '9p-for-6.7-rc1' of https://github.com/martinetd/linux:
  9p/net: fix possible memory leak in p9_check_errors()
  9p/fs: add MODULE_DESCRIPTION
  9p/net: xen: fix false positive printf format overflow warning
  9p: v9fs_listxattr: fix %s null argument warning
  9p/trans_fd: Annotate data-racy writes to file::f_flags
  fs/9p: Remove unused function declaration v9fs_inode2stat()
  9p/trans_fd: avoid sending req to a cancelled conn
This commit is contained in:
Linus Torvalds 2023-11-04 09:20:04 -10:00
commit c9b93cafb6
6 changed files with 32 additions and 19 deletions

View File

@ -732,4 +732,5 @@ module_exit(exit_v9fs)
MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>"); MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>");
MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>"); MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>"); MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>");
MODULE_DESCRIPTION("9P Client File System");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -52,7 +52,6 @@ void v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode,
unsigned int flags); unsigned int flags);
int v9fs_dir_release(struct inode *inode, struct file *filp); int v9fs_dir_release(struct inode *inode, struct file *filp);
int v9fs_file_open(struct inode *inode, struct file *file); int v9fs_file_open(struct inode *inode, struct file *file);
void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat);
int v9fs_uflags2omode(int uflags, int extended); int v9fs_uflags2omode(int uflags, int extended);
void v9fs_blank_wstat(struct p9_wstat *wstat); void v9fs_blank_wstat(struct p9_wstat *wstat);

View File

@ -68,7 +68,7 @@ ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name,
struct p9_fid *fid; struct p9_fid *fid;
int ret; int ret;
p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu\n", p9_debug(P9_DEBUG_VFS, "name = '%s' value_len = %zu\n",
name, buffer_size); name, buffer_size);
fid = v9fs_fid_lookup(dentry); fid = v9fs_fid_lookup(dentry);
if (IS_ERR(fid)) if (IS_ERR(fid))
@ -139,7 +139,8 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
{ {
return v9fs_xattr_get(dentry, NULL, buffer, buffer_size); /* Txattrwalk with an empty string lists xattrs instead */
return v9fs_xattr_get(dentry, "", buffer, buffer_size);
} }
static int v9fs_xattr_handler_get(const struct xattr_handler *handler, static int v9fs_xattr_handler_get(const struct xattr_handler *handler,

View File

@ -540,12 +540,14 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
return 0; return 0;
if (!p9_is_proto_dotl(c)) { if (!p9_is_proto_dotl(c)) {
char *ename; char *ename = NULL;
err = p9pdu_readf(&req->rc, c->proto_version, "s?d", err = p9pdu_readf(&req->rc, c->proto_version, "s?d",
&ename, &ecode); &ename, &ecode);
if (err) if (err) {
kfree(ename);
goto out_err; goto out_err;
}
if (p9_is_proto_dotu(c) && ecode < 512) if (p9_is_proto_dotu(c) && ecode < 512)
err = -ecode; err = -ecode;
@ -1979,7 +1981,7 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid,
goto error; goto error;
} }
p9_debug(P9_DEBUG_9P, p9_debug(P9_DEBUG_9P,
">>> TXATTRWALK file_fid %d, attr_fid %d name %s\n", ">>> TXATTRWALK file_fid %d, attr_fid %d name '%s'\n",
file_fid->fid, attr_fid->fid, attr_name); file_fid->fid, attr_fid->fid, attr_name);
req = p9_client_rpc(clnt, P9_TXATTRWALK, "dds", req = p9_client_rpc(clnt, P9_TXATTRWALK, "dds",

View File

@ -671,10 +671,14 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
p9_debug(P9_DEBUG_TRANS, "mux %p task %p tcall %p id %d\n", p9_debug(P9_DEBUG_TRANS, "mux %p task %p tcall %p id %d\n",
m, current, &req->tc, req->tc.id); m, current, &req->tc, req->tc.id);
if (m->err < 0)
return m->err;
spin_lock(&m->req_lock); spin_lock(&m->req_lock);
if (m->err < 0) {
spin_unlock(&m->req_lock);
return m->err;
}
WRITE_ONCE(req->status, REQ_STATUS_UNSENT); WRITE_ONCE(req->status, REQ_STATUS_UNSENT);
list_add_tail(&req->req_list, &m->unsent_req_list); list_add_tail(&req->req_list, &m->unsent_req_list);
spin_unlock(&m->req_lock); spin_unlock(&m->req_lock);
@ -832,14 +836,21 @@ static int p9_fd_open(struct p9_client *client, int rfd, int wfd)
goto out_free_ts; goto out_free_ts;
if (!(ts->rd->f_mode & FMODE_READ)) if (!(ts->rd->f_mode & FMODE_READ))
goto out_put_rd; goto out_put_rd;
/* prevent workers from hanging on IO when fd is a pipe */ /* Prevent workers from hanging on IO when fd is a pipe.
ts->rd->f_flags |= O_NONBLOCK; * It's technically possible for userspace or concurrent mounts to
* modify this flag concurrently, which will likely result in a
* broken filesystem. However, just having bad flags here should
* not crash the kernel or cause any other sort of bug, so mark this
* particular data race as intentional so that tooling (like KCSAN)
* can allow it and detect further problems.
*/
data_race(ts->rd->f_flags |= O_NONBLOCK);
ts->wr = fget(wfd); ts->wr = fget(wfd);
if (!ts->wr) if (!ts->wr)
goto out_put_rd; goto out_put_rd;
if (!(ts->wr->f_mode & FMODE_WRITE)) if (!(ts->wr->f_mode & FMODE_WRITE))
goto out_put_wr; goto out_put_wr;
ts->wr->f_flags |= O_NONBLOCK; data_race(ts->wr->f_flags |= O_NONBLOCK);
client->trans = ts; client->trans = ts;
client->status = Connected; client->status = Connected;

View File

@ -54,7 +54,6 @@ struct xen_9pfs_front_priv {
char *tag; char *tag;
struct p9_client *client; struct p9_client *client;
int num_rings;
struct xen_9pfs_dataring *rings; struct xen_9pfs_dataring *rings;
}; };
@ -131,7 +130,7 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req)
if (list_entry_is_head(priv, &xen_9pfs_devs, list)) if (list_entry_is_head(priv, &xen_9pfs_devs, list))
return -EINVAL; return -EINVAL;
num = p9_req->tc.tag % priv->num_rings; num = p9_req->tc.tag % XEN_9PFS_NUM_RINGS;
ring = &priv->rings[num]; ring = &priv->rings[num];
again: again:
@ -279,7 +278,7 @@ static void xen_9pfs_front_free(struct xen_9pfs_front_priv *priv)
list_del(&priv->list); list_del(&priv->list);
write_unlock(&xen_9pfs_lock); write_unlock(&xen_9pfs_lock);
for (i = 0; i < priv->num_rings; i++) { for (i = 0; i < XEN_9PFS_NUM_RINGS; i++) {
struct xen_9pfs_dataring *ring = &priv->rings[i]; struct xen_9pfs_dataring *ring = &priv->rings[i];
cancel_work_sync(&ring->work); cancel_work_sync(&ring->work);
@ -408,15 +407,14 @@ static int xen_9pfs_front_init(struct xenbus_device *dev)
if (p9_xen_trans.maxsize > XEN_FLEX_RING_SIZE(max_ring_order)) if (p9_xen_trans.maxsize > XEN_FLEX_RING_SIZE(max_ring_order))
p9_xen_trans.maxsize = XEN_FLEX_RING_SIZE(max_ring_order) / 2; p9_xen_trans.maxsize = XEN_FLEX_RING_SIZE(max_ring_order) / 2;
priv->num_rings = XEN_9PFS_NUM_RINGS; priv->rings = kcalloc(XEN_9PFS_NUM_RINGS, sizeof(*priv->rings),
priv->rings = kcalloc(priv->num_rings, sizeof(*priv->rings),
GFP_KERNEL); GFP_KERNEL);
if (!priv->rings) { if (!priv->rings) {
kfree(priv); kfree(priv);
return -ENOMEM; return -ENOMEM;
} }
for (i = 0; i < priv->num_rings; i++) { for (i = 0; i < XEN_9PFS_NUM_RINGS; i++) {
priv->rings[i].priv = priv; priv->rings[i].priv = priv;
ret = xen_9pfs_front_alloc_dataring(dev, &priv->rings[i], ret = xen_9pfs_front_alloc_dataring(dev, &priv->rings[i],
max_ring_order); max_ring_order);
@ -434,10 +432,11 @@ static int xen_9pfs_front_init(struct xenbus_device *dev)
if (ret) if (ret)
goto error_xenbus; goto error_xenbus;
ret = xenbus_printf(xbt, dev->nodename, "num-rings", "%u", ret = xenbus_printf(xbt, dev->nodename, "num-rings", "%u",
priv->num_rings); XEN_9PFS_NUM_RINGS);
if (ret) if (ret)
goto error_xenbus; goto error_xenbus;
for (i = 0; i < priv->num_rings; i++) {
for (i = 0; i < XEN_9PFS_NUM_RINGS; i++) {
char str[16]; char str[16];
BUILD_BUG_ON(XEN_9PFS_NUM_RINGS > 9); BUILD_BUG_ON(XEN_9PFS_NUM_RINGS > 9);