Skip to content

Commit e258ed3

Browse files
cytrinoxgregkh
authored andcommitted
ceph: fix oops due to invalid pointer for kfree() in parse_longname()
commit bc8deda upstream. 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: 101841c ("[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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 35e6fd0 commit e258ed3

1 file changed

Lines changed: 5 additions & 4 deletions

File tree

fs/ceph/crypto.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,12 +219,13 @@ static struct inode *parse_longname(const struct inode *parent,
219219
struct ceph_vino vino = { .snap = CEPH_NOSNAP };
220220
char *name_end, *inode_number;
221221
int ret = -EIO;
222-
/* NUL-terminate */
223-
char *str __free(kfree) = kmemdup_nul(name, *name_len, GFP_KERNEL);
222+
/* Snapshot name must start with an underscore */
223+
if (*name_len <= 0 || name[0] != '_')
224+
return ERR_PTR(-EIO);
225+
/* Skip initial '_' and NUL-terminate */
226+
char *str __free(kfree) = kmemdup_nul(name + 1, *name_len - 1, GFP_KERNEL);
224227
if (!str)
225228
return ERR_PTR(-ENOMEM);
226-
/* Skip initial '_' */
227-
str++;
228229
name_end = strrchr(str, '_');
229230
if (!name_end) {
230231
doutc(cl, "failed to parse long snapshot name: %s\n", str);

0 commit comments

Comments
 (0)