mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 05:44:45 +01:00
ceph: fix oops due to invalid pointer for kfree() in parse_longname()
This fixes a kernel oops when reading ceph snapshot directories (.snap),
for example by simply running `ls /mnt/my_ceph/.snap`.
The variable str is guarded by __free(kfree), but advanced by one for
skipping the initial '_' in snapshot names. Thus, kfree() is called
with an invalid pointer. This patch removes the need for advancing the
pointer so kfree() is called with correct memory pointer.
Steps to reproduce:
1. Create snapshots on a cephfs volume (I've 63 snaps in my testcase)
2. Add cephfs mount to fstab
$ echo "samba-fileserver@.files=/volumes/datapool/stuff/3461082b-ecc9-4e82-8549-3fd2590d3fb6 /mnt/test/stuff ceph acl,noatime,_netdev 0 0" >> /etc/fstab
3. Reboot the system
$ systemctl reboot
4. Check if it's really mounted
$ mount | grep stuff
5. List snapshots (expected 63 snapshots on my system)
$ ls /mnt/test/stuff/.snap
Now ls hangs forever and the kernel log shows the oops.
Cc: stable@vger.kernel.org
Fixes: 101841c383 ("[ceph] parse_longname(): strrchr() expects NUL-terminated string")
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220807
Suggested-by: Helge Deller <deller@gmx.de>
Signed-off-by: Daniel Vogelbacher <daniel@chaospixel.com>
Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
parent
bd3884a204
commit
bc8dedae02
1 changed files with 5 additions and 4 deletions
|
|
@ -166,12 +166,13 @@ static struct inode *parse_longname(const struct inode *parent,
|
|||
struct ceph_vino vino = { .snap = CEPH_NOSNAP };
|
||||
char *name_end, *inode_number;
|
||||
int ret = -EIO;
|
||||
/* NUL-terminate */
|
||||
char *str __free(kfree) = kmemdup_nul(name, *name_len, GFP_KERNEL);
|
||||
/* Snapshot name must start with an underscore */
|
||||
if (*name_len <= 0 || name[0] != '_')
|
||||
return ERR_PTR(-EIO);
|
||||
/* Skip initial '_' and NUL-terminate */
|
||||
char *str __free(kfree) = kmemdup_nul(name + 1, *name_len - 1, GFP_KERNEL);
|
||||
if (!str)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
/* Skip initial '_' */
|
||||
str++;
|
||||
name_end = strrchr(str, '_');
|
||||
if (!name_end) {
|
||||
doutc(cl, "failed to parse long snapshot name: %s\n", str);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue