]>
Commit | Line | Data |
---|---|---|
5ddacef6 SLM |
1 | From d9c2bb7a7089a59537024534b38adf6fa58c5ba4 Mon Sep 17 00:00:00 2001 |
2 | From: Gertjan Halkes <gertjan@google.com> | |
3 | Date: Wed, 5 Sep 2018 15:41:29 +0900 | |
4 | Subject: 9p: do not trust pdu content for stat item size | |
5 | ||
6 | [ Upstream commit 2803cf4379ed252894f046cb8812a48db35294e3 ] | |
7 | ||
8 | v9fs_dir_readdir() could deadloop if a struct was sent with a size set | |
9 | to -2 | |
10 | ||
11 | Link: http://lkml.kernel.org/r/1536134432-11997-1-git-send-email-asmadeus@codewreck.org | |
12 | Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=88021 | |
13 | Signed-off-by: Gertjan Halkes <gertjan@google.com> | |
14 | Signed-off-by: Dominique Martinet <dominique.martinet@cea.fr> | |
15 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
16 | --- | |
17 | fs/9p/vfs_dir.c | 8 +++----- | |
18 | net/9p/protocol.c | 3 ++- | |
19 | 2 files changed, 5 insertions(+), 6 deletions(-) | |
20 | ||
21 | diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c | |
22 | index 48db9a9f13f9..cb6c4031af55 100644 | |
23 | --- a/fs/9p/vfs_dir.c | |
24 | +++ b/fs/9p/vfs_dir.c | |
25 | @@ -105,7 +105,6 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx) | |
26 | int err = 0; | |
27 | struct p9_fid *fid; | |
28 | int buflen; | |
29 | - int reclen = 0; | |
30 | struct p9_rdir *rdir; | |
31 | struct kvec kvec; | |
32 | ||
33 | @@ -138,11 +137,10 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx) | |
34 | while (rdir->head < rdir->tail) { | |
35 | err = p9stat_read(fid->clnt, rdir->buf + rdir->head, | |
36 | rdir->tail - rdir->head, &st); | |
37 | - if (err) { | |
38 | + if (err <= 0) { | |
39 | p9_debug(P9_DEBUG_VFS, "returned %d\n", err); | |
40 | return -EIO; | |
41 | } | |
42 | - reclen = st.size+2; | |
43 | ||
44 | over = !dir_emit(ctx, st.name, strlen(st.name), | |
45 | v9fs_qid2ino(&st.qid), dt_type(&st)); | |
46 | @@ -150,8 +148,8 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx) | |
47 | if (over) | |
48 | return 0; | |
49 | ||
50 | - rdir->head += reclen; | |
51 | - ctx->pos += reclen; | |
52 | + rdir->head += err; | |
53 | + ctx->pos += err; | |
54 | } | |
55 | } | |
56 | } | |
57 | diff --git a/net/9p/protocol.c b/net/9p/protocol.c | |
58 | index 145f80518064..7f1b45c082c9 100644 | |
59 | --- a/net/9p/protocol.c | |
60 | +++ b/net/9p/protocol.c | |
61 | @@ -570,9 +570,10 @@ int p9stat_read(struct p9_client *clnt, char *buf, int len, struct p9_wstat *st) | |
62 | if (ret) { | |
63 | p9_debug(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret); | |
64 | trace_9p_protocol_dump(clnt, &fake_pdu); | |
65 | + return ret; | |
66 | } | |
67 | ||
68 | - return ret; | |
69 | + return fake_pdu.offset; | |
70 | } | |
71 | EXPORT_SYMBOL(p9stat_read); | |
72 | ||
73 | -- | |
74 | 2.19.1 | |
75 |