[PATCH] ceph: fix longname buffer overflow in ceph_fname_to_usr()

Jiangshan Yi posted 1 patch 3 weeks, 1 day ago
There is a newer version of this series
fs/ceph/crypto.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
[PATCH] ceph: fix longname buffer overflow in ceph_fname_to_usr()
Posted by Jiangshan Yi 3 weeks, 1 day ago
The snapshot longname reconstruction in ceph_fname_to_usr() uses
snprintf() to format "_<name>_<inode>" into a temporary buffer and
then memcpy()s the result into oname->name.  Since snprintf() returns
the number of characters that would have been written, the memcpy
length can exceed the NAME_MAX + 1 byte oname->name buffer when the
decoded snapshot name is long, causing a heap buffer overflow.

Check the reconstructed name length and return -ENAMETOOLONG if it
exceeds NAME_MAX, jumping to the existing cleanup path to avoid
leaking the temporary _tname buffer and the parse_longname() inode
reference.

Fixes: dd66df0053ef ("ceph: add support for encrypted snapshot names")
Cc: stable@vger.kernel.org
Signed-off-by: Jiangshan Yi <yijiangshan@kylinos.cn>
---
 fs/ceph/crypto.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/fs/ceph/crypto.c b/fs/ceph/crypto.c
index bc0a097a4cea..076e7f2f3c0e 100644
--- a/fs/ceph/crypto.c
+++ b/fs/ceph/crypto.c
@@ -403,6 +403,10 @@ int ceph_fname_to_usr(const struct ceph_fname *fname, unsigned char *tname,
 
 		name_len = snprintf(tmp_buf, sizeof(tmp_buf), "_%.*s_%llu",
 				    oname->len, oname->name, dir->i_ino);
+		if (name_len > NAME_MAX) {
+			ret = -ENAMETOOLONG;
+			goto out;
+		}
 		memcpy(oname->name, tmp_buf, name_len);
 		oname->len = name_len;
 	}
-- 
2.25.1