diff --git a/fs/ceph/crypto.c b/fs/ceph/crypto.c index bc0a097a4cea..845b69ba890c 100644 --- a/fs/ceph/crypto.c +++ b/fs/ceph/crypto.c @@ -313,6 +313,7 @@ int ceph_fname_to_usr(const struct ceph_fname *fname, unsigned char *tname, struct fscrypt_str iname; char *name = fname->name; int name_len = fname->name_len; + int dst_len; int ret; if (WARN_ON_ONCE(tname && is_vmalloc_addr(tname))) @@ -387,6 +388,9 @@ int ceph_fname_to_usr(const struct ceph_fname *fname, unsigned char *tname, iname.len = fname->ctext_len; } + /* oname->len is overwritten by the decryption below */ + dst_len = oname->len; + _oname.name = unlikely(is_vmalloc_addr(oname->name)) ? tname : oname->name; _oname.len = oname->len; @@ -403,6 +407,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 > dst_len) { + ret = -ENAMETOOLONG; + goto out; + } memcpy(oname->name, tmp_buf, name_len); oname->len = name_len; }