| From e127daee55b27e4dce1403e9b2e2b2323cfece4a Mon Sep 17 00:00:00 2001 |
| From: Dominique Martinet <dominique.martinet@cea.fr> |
| Date: Sat, 8 Sep 2018 00:36:08 +0900 |
| Subject: 9p: p9dirent_read: check network-provided name length |
| |
| [ Upstream commit ef5305f1f72eb1cfcda25c382bb0368509c0385b ] |
| |
| strcpy to dirent->d_name could overflow the buffer, use strscpy to check |
| the provided string length and error out if the size was too big. |
| |
| While we are here, make the function return an error when the pdu |
| parsing failed, instead of returning the pdu offset as if it had been a |
| success... |
| |
| Link: http://lkml.kernel.org/r/1536339057-21974-4-git-send-email-asmadeus@codewreck.org |
| Addresses-Coverity-ID: 139133 ("Copy into fixed size buffer") |
| Signed-off-by: Dominique Martinet <dominique.martinet@cea.fr> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/9p/protocol.c | 12 +++++++++--- |
| 1 file changed, 9 insertions(+), 3 deletions(-) |
| |
| diff --git a/net/9p/protocol.c b/net/9p/protocol.c |
| index b4d80c533f89..462ba144cb39 100644 |
| --- a/net/9p/protocol.c |
| +++ b/net/9p/protocol.c |
| @@ -623,13 +623,19 @@ int p9dirent_read(struct p9_client *clnt, char *buf, int len, |
| if (ret) { |
| p9_debug(P9_DEBUG_9P, "<<< p9dirent_read failed: %d\n", ret); |
| trace_9p_protocol_dump(clnt, &fake_pdu); |
| - goto out; |
| + return ret; |
| } |
| |
| - strcpy(dirent->d_name, nameptr); |
| + ret = strscpy(dirent->d_name, nameptr, sizeof(dirent->d_name)); |
| + if (ret < 0) { |
| + p9_debug(P9_DEBUG_ERROR, |
| + "On the wire dirent name too long: %s\n", |
| + nameptr); |
| + kfree(nameptr); |
| + return ret; |
| + } |
| kfree(nameptr); |
| |
| -out: |
| return fake_pdu.offset; |
| } |
| EXPORT_SYMBOL(p9dirent_read); |
| -- |
| 2.20.1 |
| |