mirror of
https://github.com/torvalds/linux.git
synced 2026-09-25 17:42:03 +02:00
[ceph] parse_longname(): strrchr() expects NUL-terminated string
... and parse_longname() is not guaranteed that. That's the reason
why it uses kmemdup_nul() to build the argument for kstrtou64();
the problem is, kstrtou64() is not the only thing that need it.
Just get a NUL-terminated copy of the entire thing and be done
with that...
Fixes: dd66df0053 "ceph: add support for encrypted snapshot names"
Tested-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
19272b37aa
commit
101841c383
|
|
@ -215,35 +215,31 @@ static struct inode *parse_longname(const struct inode *parent,
|
||||||
struct ceph_client *cl = ceph_inode_to_client(parent);
|
struct ceph_client *cl = ceph_inode_to_client(parent);
|
||||||
struct inode *dir = NULL;
|
struct inode *dir = NULL;
|
||||||
struct ceph_vino vino = { .snap = CEPH_NOSNAP };
|
struct ceph_vino vino = { .snap = CEPH_NOSNAP };
|
||||||
char *inode_number;
|
char *name_end, *inode_number;
|
||||||
char *name_end;
|
|
||||||
int orig_len = *name_len;
|
|
||||||
int ret = -EIO;
|
int ret = -EIO;
|
||||||
|
/* NUL-terminate */
|
||||||
|
char *str __free(kfree) = kmemdup_nul(name, *name_len, GFP_KERNEL);
|
||||||
|
if (!str)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
/* Skip initial '_' */
|
/* Skip initial '_' */
|
||||||
name++;
|
str++;
|
||||||
name_end = strrchr(name, '_');
|
name_end = strrchr(str, '_');
|
||||||
if (!name_end) {
|
if (!name_end) {
|
||||||
doutc(cl, "failed to parse long snapshot name: %s\n", name);
|
doutc(cl, "failed to parse long snapshot name: %s\n", str);
|
||||||
return ERR_PTR(-EIO);
|
return ERR_PTR(-EIO);
|
||||||
}
|
}
|
||||||
*name_len = (name_end - name);
|
*name_len = (name_end - str);
|
||||||
if (*name_len <= 0) {
|
if (*name_len <= 0) {
|
||||||
pr_err_client(cl, "failed to parse long snapshot name\n");
|
pr_err_client(cl, "failed to parse long snapshot name\n");
|
||||||
return ERR_PTR(-EIO);
|
return ERR_PTR(-EIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the inode number */
|
/* Get the inode number */
|
||||||
inode_number = kmemdup_nul(name_end + 1,
|
inode_number = name_end + 1;
|
||||||
orig_len - *name_len - 2,
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!inode_number)
|
|
||||||
return ERR_PTR(-ENOMEM);
|
|
||||||
ret = kstrtou64(inode_number, 10, &vino.ino);
|
ret = kstrtou64(inode_number, 10, &vino.ino);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
doutc(cl, "failed to parse inode number: %s\n", name);
|
doutc(cl, "failed to parse inode number: %s\n", str);
|
||||||
dir = ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* And finally the inode */
|
/* And finally the inode */
|
||||||
|
|
@ -254,9 +250,6 @@ static struct inode *parse_longname(const struct inode *parent,
|
||||||
if (IS_ERR(dir))
|
if (IS_ERR(dir))
|
||||||
doutc(cl, "can't find inode %s (%s)\n", inode_number, name);
|
doutc(cl, "can't find inode %s (%s)\n", inode_number, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
|
||||||
kfree(inode_number);
|
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user