Skip to content

Commit 101841c

Browse files
author
Al Viro
committed
[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: dd66df0 "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>
1 parent 19272b3 commit 101841c

1 file changed

Lines changed: 12 additions & 19 deletions

File tree

fs/ceph/crypto.c

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -215,35 +215,31 @@ static struct inode *parse_longname(const struct inode *parent,
215215
struct ceph_client *cl = ceph_inode_to_client(parent);
216216
struct inode *dir = NULL;
217217
struct ceph_vino vino = { .snap = CEPH_NOSNAP };
218-
char *inode_number;
219-
char *name_end;
220-
int orig_len = *name_len;
218+
char *name_end, *inode_number;
221219
int ret = -EIO;
222-
220+
/* NUL-terminate */
221+
char *str __free(kfree) = kmemdup_nul(name, *name_len, GFP_KERNEL);
222+
if (!str)
223+
return ERR_PTR(-ENOMEM);
223224
/* Skip initial '_' */
224-
name++;
225-
name_end = strrchr(name, '_');
225+
str++;
226+
name_end = strrchr(str, '_');
226227
if (!name_end) {
227-
doutc(cl, "failed to parse long snapshot name: %s\n", name);
228+
doutc(cl, "failed to parse long snapshot name: %s\n", str);
228229
return ERR_PTR(-EIO);
229230
}
230-
*name_len = (name_end - name);
231+
*name_len = (name_end - str);
231232
if (*name_len <= 0) {
232233
pr_err_client(cl, "failed to parse long snapshot name\n");
233234
return ERR_PTR(-EIO);
234235
}
235236

236237
/* Get the inode number */
237-
inode_number = kmemdup_nul(name_end + 1,
238-
orig_len - *name_len - 2,
239-
GFP_KERNEL);
240-
if (!inode_number)
241-
return ERR_PTR(-ENOMEM);
238+
inode_number = name_end + 1;
242239
ret = kstrtou64(inode_number, 10, &vino.ino);
243240
if (ret) {
244-
doutc(cl, "failed to parse inode number: %s\n", name);
245-
dir = ERR_PTR(ret);
246-
goto out;
241+
doutc(cl, "failed to parse inode number: %s\n", str);
242+
return ERR_PTR(ret);
247243
}
248244

249245
/* And finally the inode */
@@ -254,9 +250,6 @@ static struct inode *parse_longname(const struct inode *parent,
254250
if (IS_ERR(dir))
255251
doutc(cl, "can't find inode %s (%s)\n", inode_number, name);
256252
}
257-
258-
out:
259-
kfree(inode_number);
260253
return dir;
261254
}
262255

0 commit comments

Comments
 (0)