aboutsummaryrefslogtreecommitdiff
path: root/hw/9pfs
diff options
context:
space:
mode:
authorChristian Schoenebeck <qemu_oss@crudebyte.com>2020-02-08 09:24:19 +0100
committerGreg Kurz <groug@kaod.org>2020-02-08 09:28:43 +0100
commite16453a31a00c1c0a199cab0617e8aa888f6419a (patch)
tree2512a676c553d59ee0f223942f4324a5dd8f701f /hw/9pfs
parent2e2293c238d4daa791ab7ff60b326a322892df3a (diff)
downloadqemu-e16453a31a00c1c0a199cab0617e8aa888f6419a.zip
qemu-e16453a31a00c1c0a199cab0617e8aa888f6419a.tar.gz
qemu-e16453a31a00c1c0a199cab0617e8aa888f6419a.tar.bz2
9pfs: require msize >= 4096
A client establishes a session by sending a Tversion request along with a 'msize' parameter which client uses to suggest 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 4096 then deny session by server immediately with an error response (Rlerror for "9P2000.L" clients or Rerror for "9P2000.u" clients) instead of replying with Rversion. So far any msize submitted by client with Tversion was simply accepted by server without any check. Introduction of some minimum msize makes sense, because e.g. a msize < 7 would not allow any subsequent 9p operation at all, because 7 is the size of the header section common by all 9p message types. A substantial higher value of 4096 was chosen though to prevent potential issues with some message types. E.g. Rreadlink may yield up to a size of PATH_MAX which is usually 4096, and like almost all 9p message types, Rreadlink is not allowed to be truncated by the 9p protocol. This chosen size also prevents a similar issue with Rreaddir responses (provided client always sends adequate 'count' parameter with Treaddir), because even though directory entries retrieval may be split up over several T/Rreaddir messages; a Rreaddir response must not truncate individual directory entries though. So msize should be large enough to return at least one directory entry with the longest possible file name supported by host. Most file systems support a max. file name length of 255. Largest known file name lenght limit would be currently ReiserFS with max. 4032 bytes, which is also covered by this min. msize value because 4032 + 35 < 4096. Furthermore 4096 is already the minimum msize of the Linux kernel's 9pfs client. Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com> Reviewed-by: Greg Kurz <groug@kaod.org> Message-Id: <8ceecb7fb9fdbeabbe55c04339349a36929fb8e3.1579567019.git.qemu_oss@crudebyte.com> Signed-off-by: Greg Kurz <groug@kaod.org>
Diffstat (limited to 'hw/9pfs')
-rw-r--r--hw/9pfs/9p.c12
-rw-r--r--hw/9pfs/9p.h11
2 files changed, 23 insertions, 0 deletions
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index b0e445d..c63f549 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;
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
index 8d07a0b..b8f72a3 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