Skip to content

Commit bdafff6

Browse files
committed
Merge tag '9p-for-6.15-rc1' of https://github.com/martinetd/linux
Pull 9p updates from Dominique Martinet: - fix handling of bogus (negative/too long) replies - fix crash on mkdir with ACLs (... looks like nobody is using ACLs with semi-recent kernels...) - ipv6 support for trans=tcp - minor concurrency fix to make syzbot happy - minor cleanup * tag '9p-for-6.15-rc1' of https://github.com/martinetd/linux: docs: fs/9p: Add missing "not" in cache documentation 9p: Use hashtable.h for hash_errmap Documentation/fs/9p: fix broken link 9p/trans_fd: mark concurrent read and writes to p9_conn->err 9p/net: return error on bogus (longer than requested) replies 9p/net: fix improper handling of bogus negative read/write replies fs/9p: fix NULL pointer dereference on mkdir net/9p/fd: support ipv6 for trans=tcp
2 parents 5916a6f + 4210030 commit bdafff6

File tree

5 files changed

+73
-73
lines changed

5 files changed

+73
-73
lines changed

Documentation/filesystems/9p.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ For remote file server::
4040

4141
mount -t 9p 10.10.1.2 /mnt/9
4242

43-
For Plan 9 From User Space applications (http://swtch.com/plan9)::
43+
For Plan 9 From User Space applications (https://9fans.github.io/plan9port/)::
4444

4545
mount -t 9p `namespace`/acme /mnt/9 -o trans=unix,uname=$USER
4646

@@ -165,8 +165,8 @@ Options
165165
do not necessarily validate cached values on the server. In other
166166
words changes on the server are not guaranteed to be reflected
167167
on the client system. Only use this mode of operation if you
168-
have an exclusive mount and the server will modify the filesystem
169-
underneath you.
168+
have an exclusive mount and the server will not modify the
169+
filesystem underneath you.
170170

171171
debug=n specifies debug level. The debug level is a bitmask.
172172

fs/9p/vfs_inode_dotl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,8 @@ static struct dentry *v9fs_vfs_mkdir_dotl(struct mnt_idmap *idmap,
407407
err);
408408
goto error;
409409
}
410-
v9fs_fid_add(dentry, &fid);
411410
v9fs_set_create_acl(inode, fid, dacl, pacl);
411+
v9fs_fid_add(dentry, &fid);
412412
d_instantiate(dentry, inode);
413413
err = 0;
414414
inc_nlink(dir);

net/9p/client.c

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,7 +1548,8 @@ p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to,
15481548
struct p9_client *clnt = fid->clnt;
15491549
struct p9_req_t *req;
15501550
int count = iov_iter_count(to);
1551-
int rsize, received, non_zc = 0;
1551+
u32 rsize, received;
1552+
bool non_zc = false;
15521553
char *dataptr;
15531554

15541555
*err = 0;
@@ -1571,7 +1572,7 @@ p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to,
15711572
0, 11, "dqd", fid->fid,
15721573
offset, rsize);
15731574
} else {
1574-
non_zc = 1;
1575+
non_zc = true;
15751576
req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset,
15761577
rsize);
15771578
}
@@ -1592,11 +1593,13 @@ p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to,
15921593
return 0;
15931594
}
15941595
if (rsize < received) {
1595-
pr_err("bogus RREAD count (%d > %d)\n", received, rsize);
1596-
received = rsize;
1596+
pr_err("bogus RREAD count (%u > %u)\n", received, rsize);
1597+
*err = -EIO;
1598+
p9_req_put(clnt, req);
1599+
return 0;
15971600
}
15981601

1599-
p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", received);
1602+
p9_debug(P9_DEBUG_9P, "<<< RREAD count %u\n", received);
16001603

16011604
if (non_zc) {
16021605
int n = copy_to_iter(dataptr, received, to);
@@ -1623,17 +1626,17 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err)
16231626
*err = 0;
16241627

16251628
while (iov_iter_count(from)) {
1626-
int count = iov_iter_count(from);
1627-
int rsize = fid->iounit;
1628-
int written;
1629+
size_t count = iov_iter_count(from);
1630+
u32 rsize = fid->iounit;
1631+
u32 written;
16291632

16301633
if (!rsize || rsize > clnt->msize - P9_IOHDRSZ)
16311634
rsize = clnt->msize - P9_IOHDRSZ;
16321635

16331636
if (count < rsize)
16341637
rsize = count;
16351638

1636-
p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d (/%d)\n",
1639+
p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %u (/%zu)\n",
16371640
fid->fid, offset, rsize, count);
16381641

16391642
/* Don't bother zerocopy for small IO (< 1024) */
@@ -1659,11 +1662,14 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err)
16591662
break;
16601663
}
16611664
if (rsize < written) {
1662-
pr_err("bogus RWRITE count (%d > %d)\n", written, rsize);
1663-
written = rsize;
1665+
pr_err("bogus RWRITE count (%u > %u)\n", written, rsize);
1666+
*err = -EIO;
1667+
iov_iter_revert(from, count - iov_iter_count(from));
1668+
p9_req_put(clnt, req);
1669+
break;
16641670
}
16651671

1666-
p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", written);
1672+
p9_debug(P9_DEBUG_9P, "<<< RWRITE count %u\n", written);
16671673

16681674
p9_req_put(clnt, req);
16691675
iov_iter_revert(from, count - written - iov_iter_count(from));
@@ -1712,7 +1718,7 @@ p9_client_write_subreq(struct netfs_io_subrequest *subreq)
17121718

17131719
if (written > len) {
17141720
pr_err("bogus RWRITE count (%d > %u)\n", written, len);
1715-
written = len;
1721+
written = -EIO;
17161722
}
17171723

17181724
p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", len);
@@ -2098,7 +2104,8 @@ EXPORT_SYMBOL_GPL(p9_client_xattrcreate);
20982104

20992105
int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
21002106
{
2101-
int err, rsize, non_zc = 0;
2107+
int err, non_zc = 0;
2108+
u32 rsize;
21022109
struct p9_client *clnt;
21032110
struct p9_req_t *req;
21042111
char *dataptr;
@@ -2107,7 +2114,7 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
21072114

21082115
iov_iter_kvec(&to, ITER_DEST, &kv, 1, count);
21092116

2110-
p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n",
2117+
p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %u\n",
21112118
fid->fid, offset, count);
21122119

21132120
clnt = fid->clnt;
@@ -2142,11 +2149,12 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
21422149
goto free_and_error;
21432150
}
21442151
if (rsize < count) {
2145-
pr_err("bogus RREADDIR count (%d > %d)\n", count, rsize);
2146-
count = rsize;
2152+
pr_err("bogus RREADDIR count (%u > %u)\n", count, rsize);
2153+
err = -EIO;
2154+
goto free_and_error;
21472155
}
21482156

2149-
p9_debug(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count);
2157+
p9_debug(P9_DEBUG_9P, "<<< RREADDIR count %u\n", count);
21502158

21512159
if (non_zc)
21522160
memmove(data, dataptr, count);

net/9p/error.c

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/list.h>
1717
#include <linux/jhash.h>
1818
#include <linux/errno.h>
19+
#include <linux/hashtable.h>
1920
#include <net/9p/9p.h>
2021

2122
/**
@@ -33,8 +34,8 @@ struct errormap {
3334
struct hlist_node list;
3435
};
3536

36-
#define ERRHASHSZ 32
37-
static struct hlist_head hash_errmap[ERRHASHSZ];
37+
#define ERRHASH_BITS 5
38+
static DEFINE_HASHTABLE(hash_errmap, ERRHASH_BITS);
3839

3940
/* FixMe - reduce to a reasonable size */
4041
static struct errormap errmap[] = {
@@ -176,18 +177,14 @@ static struct errormap errmap[] = {
176177
int p9_error_init(void)
177178
{
178179
struct errormap *c;
179-
int bucket;
180-
181-
/* initialize hash table */
182-
for (bucket = 0; bucket < ERRHASHSZ; bucket++)
183-
INIT_HLIST_HEAD(&hash_errmap[bucket]);
180+
u32 hash;
184181

185182
/* load initial error map into hash table */
186183
for (c = errmap; c->name; c++) {
187184
c->namelen = strlen(c->name);
188-
bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ;
185+
hash = jhash(c->name, c->namelen, 0);
189186
INIT_HLIST_NODE(&c->list);
190-
hlist_add_head(&c->list, &hash_errmap[bucket]);
187+
hash_add(hash_errmap, &c->list, hash);
191188
}
192189

193190
return 1;
@@ -205,12 +202,12 @@ int p9_errstr2errno(char *errstr, int len)
205202
{
206203
int errno;
207204
struct errormap *c;
208-
int bucket;
205+
u32 hash;
209206

210207
errno = 0;
211208
c = NULL;
212-
bucket = jhash(errstr, len, 0) % ERRHASHSZ;
213-
hlist_for_each_entry(c, &hash_errmap[bucket], list) {
209+
hash = jhash(errstr, len, 0);
210+
hash_for_each_possible(hash_errmap, c, list, hash) {
214211
if (c->namelen == len && !memcmp(c->name, errstr, len)) {
215212
errno = c->val;
216213
break;

net/9p/trans_fd.c

Lines changed: 34 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1212

1313
#include <linux/in.h>
14+
#include <linux/in6.h>
1415
#include <linux/module.h>
1516
#include <linux/net.h>
1617
#include <linux/ipv6.h>
@@ -191,12 +192,13 @@ static void p9_conn_cancel(struct p9_conn *m, int err)
191192

192193
spin_lock(&m->req_lock);
193194

194-
if (m->err) {
195+
if (READ_ONCE(m->err)) {
195196
spin_unlock(&m->req_lock);
196197
return;
197198
}
198199

199-
m->err = err;
200+
WRITE_ONCE(m->err, err);
201+
ASSERT_EXCLUSIVE_WRITER(m->err);
200202

201203
list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) {
202204
list_move(&req->req_list, &cancel_list);
@@ -283,7 +285,7 @@ static void p9_read_work(struct work_struct *work)
283285

284286
m = container_of(work, struct p9_conn, rq);
285287

286-
if (m->err < 0)
288+
if (READ_ONCE(m->err) < 0)
287289
return;
288290

289291
p9_debug(P9_DEBUG_TRANS, "start mux %p pos %zd\n", m, m->rc.offset);
@@ -450,7 +452,7 @@ static void p9_write_work(struct work_struct *work)
450452

451453
m = container_of(work, struct p9_conn, wq);
452454

453-
if (m->err < 0) {
455+
if (READ_ONCE(m->err) < 0) {
454456
clear_bit(Wworksched, &m->wsched);
455457
return;
456458
}
@@ -622,7 +624,7 @@ static void p9_poll_mux(struct p9_conn *m)
622624
__poll_t n;
623625
int err = -ECONNRESET;
624626

625-
if (m->err < 0)
627+
if (READ_ONCE(m->err) < 0)
626628
return;
627629

628630
n = p9_fd_poll(m->client, NULL, &err);
@@ -665,6 +667,7 @@ static void p9_poll_mux(struct p9_conn *m)
665667
static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
666668
{
667669
__poll_t n;
670+
int err;
668671
struct p9_trans_fd *ts = client->trans;
669672
struct p9_conn *m = &ts->conn;
670673

@@ -673,9 +676,10 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
673676

674677
spin_lock(&m->req_lock);
675678

676-
if (m->err < 0) {
679+
err = READ_ONCE(m->err);
680+
if (err < 0) {
677681
spin_unlock(&m->req_lock);
678-
return m->err;
682+
return err;
679683
}
680684

681685
WRITE_ONCE(req->status, REQ_STATUS_UNSENT);
@@ -954,64 +958,55 @@ static void p9_fd_close(struct p9_client *client)
954958
kfree(ts);
955959
}
956960

957-
/*
958-
* stolen from NFS - maybe should be made a generic function?
959-
*/
960-
static inline int valid_ipaddr4(const char *buf)
961-
{
962-
int rc, count, in[4];
963-
964-
rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]);
965-
if (rc != 4)
966-
return -EINVAL;
967-
for (count = 0; count < 4; count++) {
968-
if (in[count] > 255)
969-
return -EINVAL;
970-
}
971-
return 0;
972-
}
973-
974961
static int p9_bind_privport(struct socket *sock)
975962
{
976-
struct sockaddr_in cl;
963+
struct sockaddr_storage stor = { 0 };
977964
int port, err = -EINVAL;
978965

979-
memset(&cl, 0, sizeof(cl));
980-
cl.sin_family = AF_INET;
981-
cl.sin_addr.s_addr = htonl(INADDR_ANY);
966+
stor.ss_family = sock->ops->family;
967+
if (stor.ss_family == AF_INET)
968+
((struct sockaddr_in *)&stor)->sin_addr.s_addr = htonl(INADDR_ANY);
969+
else
970+
((struct sockaddr_in6 *)&stor)->sin6_addr = in6addr_any;
982971
for (port = p9_ipport_resv_max; port >= p9_ipport_resv_min; port--) {
983-
cl.sin_port = htons((ushort)port);
984-
err = kernel_bind(sock, (struct sockaddr *)&cl, sizeof(cl));
972+
if (stor.ss_family == AF_INET)
973+
((struct sockaddr_in *)&stor)->sin_port = htons((ushort)port);
974+
else
975+
((struct sockaddr_in6 *)&stor)->sin6_port = htons((ushort)port);
976+
err = kernel_bind(sock, (struct sockaddr *)&stor, sizeof(stor));
985977
if (err != -EADDRINUSE)
986978
break;
987979
}
988980
return err;
989981
}
990982

991-
992983
static int
993984
p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
994985
{
995986
int err;
987+
char port_str[6];
996988
struct socket *csocket;
997-
struct sockaddr_in sin_server;
989+
struct sockaddr_storage stor = { 0 };
998990
struct p9_fd_opts opts;
999991

1000992
err = parse_opts(args, &opts);
1001993
if (err < 0)
1002994
return err;
1003995

1004-
if (addr == NULL || valid_ipaddr4(addr) < 0)
996+
if (!addr)
1005997
return -EINVAL;
1006998

999+
sprintf(port_str, "%u", opts.port);
1000+
err = inet_pton_with_scope(current->nsproxy->net_ns, AF_UNSPEC, addr,
1001+
port_str, &stor);
1002+
if (err < 0)
1003+
return err;
1004+
10071005
csocket = NULL;
10081006

10091007
client->trans_opts.tcp.port = opts.port;
10101008
client->trans_opts.tcp.privport = opts.privport;
1011-
sin_server.sin_family = AF_INET;
1012-
sin_server.sin_addr.s_addr = in_aton(addr);
1013-
sin_server.sin_port = htons(opts.port);
1014-
err = __sock_create(current->nsproxy->net_ns, PF_INET,
1009+
err = __sock_create(current->nsproxy->net_ns, stor.ss_family,
10151010
SOCK_STREAM, IPPROTO_TCP, &csocket, 1);
10161011
if (err) {
10171012
pr_err("%s (%d): problem creating socket\n",
@@ -1030,8 +1025,8 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
10301025
}
10311026

10321027
err = READ_ONCE(csocket->ops)->connect(csocket,
1033-
(struct sockaddr *)&sin_server,
1034-
sizeof(struct sockaddr_in), 0);
1028+
(struct sockaddr *)&stor,
1029+
sizeof(stor), 0);
10351030
if (err < 0) {
10361031
pr_err("%s (%d): problem connecting socket to %s\n",
10371032
__func__, task_pid_nr(current), addr);

0 commit comments

Comments
 (0)