aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-02-10 16:07:29 +0000
committerPeter Maydell <peter.maydell@linaro.org>2020-02-10 16:07:29 +0000
commit2b8a51cdb3e8d15a5c35de7a2e76a813ae7358f0 (patch)
treec82e3e89f982c292177cd066066fe246b2cb10d3 /hw
parent73d336510cf118fcc2ee7e98e774a193cf661614 (diff)
parent2822602cbe2be98229b882101dfdb9d3a738c611 (diff)
Merge remote-tracking branch 'remotes/gkurz/tags/9p-next-2020-02-08' into staging
9p patches: - some more protocol sanity checks - qtest for readdir - Christian Schoenebeck now official reviewer # gpg: Signature made Sat 08 Feb 2020 08:38:10 GMT # gpg: using RSA key B4828BAF943140CEF2A3491071D4D5E5822F73D6 # gpg: Good signature from "Greg Kurz <groug@kaod.org>" [full] # gpg: aka "Gregory Kurz <gregory.kurz@free.fr>" [full] # gpg: aka "[jpeg image of size 3330]" [full] # Primary key fingerprint: B482 8BAF 9431 40CE F2A3 4910 71D4 D5E5 822F 73D6 * remotes/gkurz/tags/9p-next-2020-02-08: MAINTAINERS: 9pfs: Add myself as reviewer tests/virtio-9p: added readdir test hw/9pfs/9p-synth: added directory for readdir test 9pfs: validate count sent by client with T_readdir 9pfs: require msize >= 4096 tests/virtio-9p: add terminating null in v9fs_string_read() Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/9pfs/9p-synth.c19
-rw-r--r--hw/9pfs/9p-synth.h5
-rw-r--r--hw/9pfs/9p.c21
-rw-r--r--hw/9pfs/9p.h11
4 files changed, 56 insertions, 0 deletions
diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
index 54239c9bbf..7eb210ffa8 100644
--- a/hw/9pfs/9p-synth.c
+++ b/hw/9pfs/9p-synth.c
@@ -578,6 +578,25 @@ static int synth_init(FsContext *ctx, Error **errp)
NULL, v9fs_synth_qtest_flush_write,
ctx);
assert(!ret);
+
+ /* Directory for READDIR test */
+ {
+ V9fsSynthNode *dir = NULL;
+ ret = qemu_v9fs_synth_mkdir(
+ NULL, 0700, QTEST_V9FS_SYNTH_READDIR_DIR, &dir
+ );
+ assert(!ret);
+ for (i = 0; i < QTEST_V9FS_SYNTH_READDIR_NFILES; ++i) {
+ char *name = g_strdup_printf(
+ QTEST_V9FS_SYNTH_READDIR_FILE, i
+ );
+ ret = qemu_v9fs_synth_add_file(
+ dir, 0, name, NULL, NULL, ctx
+ );
+ assert(!ret);
+ g_free(name);
+ }
+ }
}
return 0;
diff --git a/hw/9pfs/9p-synth.h b/hw/9pfs/9p-synth.h
index af7a993a1e..036d7e4a5b 100644
--- a/hw/9pfs/9p-synth.h
+++ b/hw/9pfs/9p-synth.h
@@ -55,6 +55,11 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode,
#define QTEST_V9FS_SYNTH_LOPEN_FILE "LOPEN"
#define QTEST_V9FS_SYNTH_WRITE_FILE "WRITE"
+/* for READDIR test */
+#define QTEST_V9FS_SYNTH_READDIR_DIR "ReadDirDir"
+#define QTEST_V9FS_SYNTH_READDIR_FILE "ReadDirFile%d"
+#define QTEST_V9FS_SYNTH_READDIR_NFILES 100
+
/* Any write to the "FLUSH" file is handled one byte at a time by the
* backend. If the byte is zero, the backend returns success (ie, 1),
* otherwise it forces the server to try again forever. Thus allowing
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index b0e445d6bd..9e046f7acb 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -1363,8 +1363,20 @@ static void coroutine_fn v9fs_version(void *opaque)
s->proto_version = V9FS_PROTO_2000L;
} else {
v9fs_string_sprintf(&version, "unknown");
+ /* skip min. msize check, reporting invalid version has priority */
+ goto marshal;
}
+ if (s->msize < P9_MIN_MSIZE) {
+ err = -EMSGSIZE;
+ error_report(
+ "9pfs: Client requested msize < minimum msize ("
+ stringify(P9_MIN_MSIZE) ") supported by this server."
+ );
+ goto out;
+ }
+
+marshal:
err = pdu_marshal(pdu, offset, "ds", s->msize, &version);
if (err < 0) {
goto out;
@@ -2422,6 +2434,7 @@ static void coroutine_fn v9fs_readdir(void *opaque)
int32_t count;
uint32_t max_count;
V9fsPDU *pdu = opaque;
+ V9fsState *s = pdu->s;
retval = pdu_unmarshal(pdu, offset, "dqd", &fid,
&initial_offset, &max_count);
@@ -2430,6 +2443,14 @@ static void coroutine_fn v9fs_readdir(void *opaque)
}
trace_v9fs_readdir(pdu->tag, pdu->id, fid, initial_offset, max_count);
+ /* Enough space for a R_readdir header: size[4] Rreaddir tag[2] count[4] */
+ if (max_count > s->msize - 11) {
+ max_count = s->msize - 11;
+ warn_report_once(
+ "9p: bad client: T_readdir with count > msize - 11"
+ );
+ }
+
fidp = get_fid(pdu, fid);
if (fidp == NULL) {
retval = -EINVAL;
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
index 8d07a0b301..b8f72a3bd9 100644
--- a/hw/9pfs/9p.h
+++ b/hw/9pfs/9p.h
@@ -100,6 +100,17 @@ typedef enum P9ProtoVersion {
V9FS_PROTO_2000L = 0x02,
} P9ProtoVersion;
+/**
+ * @brief Minimum message size supported by this 9pfs server.
+ *
+ * A client establishes a session by sending a Tversion request along with a
+ * 'msize' parameter which suggests the server a maximum message size ever to be
+ * used for communication (for both requests and replies) between client and
+ * server during that session. If client suggests a 'msize' smaller than this
+ * value then session is denied by server with an error response.
+ */
+#define P9_MIN_MSIZE 4096
+
#define P9_NOTAG UINT16_MAX
#define P9_NOFID UINT32_MAX
#define P9_MAXWELEM 16