Merge tag 'fuse-fixes-5.15-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse

Pull fuse fixes from Miklos Szeredi:
"Syzbot discovered a race in case of reusing the fuse sb (introduced in
this cycle).

Fix it by doing the s_fs_info initialization at the proper place"

* tag 'fuse-fixes-5.15-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse:
fuse: clean up error exits in fuse_fill_super()
fuse: always initialize sb->s_fs_info
fuse: clean up fuse_mount destruction
fuse: get rid of fuse_put_super()
fuse: check s_root when destroying sb

+46 -56
+3
fs/fuse/fuse_i.h
··· 1121 1121 */ 1122 1122 void fuse_conn_destroy(struct fuse_mount *fm); 1123 1123 1124 + /* Drop the connection and free the fuse mount */ 1125 + void fuse_mount_destroy(struct fuse_mount *fm); 1126 + 1124 1127 /** 1125 1128 * Add connection to control filesystem 1126 1129 */
+39 -48
fs/fuse/inode.c
··· 457 457 } 458 458 } 459 459 460 - static void fuse_put_super(struct super_block *sb) 461 - { 462 - struct fuse_mount *fm = get_fuse_mount_super(sb); 463 - 464 - fuse_conn_put(fm->fc); 465 - kfree(fm); 466 - } 467 - 468 460 static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr) 469 461 { 470 462 stbuf->f_type = FUSE_SUPER_MAGIC; ··· 995 1003 .evict_inode = fuse_evict_inode, 996 1004 .write_inode = fuse_write_inode, 997 1005 .drop_inode = generic_delete_inode, 998 - .put_super = fuse_put_super, 999 1006 .umount_begin = fuse_umount_begin, 1000 1007 .statfs = fuse_statfs, 1001 1008 .sync_fs = fuse_sync_fs, ··· 1415 1424 if (!fm) 1416 1425 return -ENOMEM; 1417 1426 1427 + fm->fc = fuse_conn_get(fc); 1418 1428 fsc->s_fs_info = fm; 1419 1429 sb = sget_fc(fsc, NULL, set_anon_super_fc); 1420 - if (IS_ERR(sb)) { 1421 - kfree(fm); 1430 + if (fsc->s_fs_info) 1431 + fuse_mount_destroy(fm); 1432 + if (IS_ERR(sb)) 1422 1433 return PTR_ERR(sb); 1423 - } 1424 - fm->fc = fuse_conn_get(fc); 1425 1434 1426 1435 /* Initialize superblock, making @mp_fi its root */ 1427 1436 err = fuse_fill_super_submount(sb, mp_fi); 1428 1437 if (err) { 1429 - fuse_conn_put(fc); 1430 - kfree(fm); 1431 - sb->s_fs_info = NULL; 1432 1438 deactivate_locked_super(sb); 1433 1439 return err; 1434 1440 } ··· 1557 1569 { 1558 1570 struct fuse_fs_context *ctx = fsc->fs_private; 1559 1571 int err; 1560 - struct fuse_conn *fc; 1561 - struct fuse_mount *fm; 1562 1572 1563 1573 if (!ctx->file || !ctx->rootmode_present || 1564 1574 !ctx->user_id_present || !ctx->group_id_present) ··· 1566 1580 * Require mount to happen from the same user namespace which 1567 1581 * opened /dev/fuse to prevent potential attacks. 1568 1582 */ 1569 - err = -EINVAL; 1570 1583 if ((ctx->file->f_op != &fuse_dev_operations) || 1571 1584 (ctx->file->f_cred->user_ns != sb->s_user_ns)) 1572 - goto err; 1585 + return -EINVAL; 1573 1586 ctx->fudptr = &ctx->file->private_data; 1574 - 1575 - fc = kmalloc(sizeof(*fc), GFP_KERNEL); 1576 - err = -ENOMEM; 1577 - if (!fc) 1578 - goto err; 1579 - 1580 - fm = kzalloc(sizeof(*fm), GFP_KERNEL); 1581 - if (!fm) { 1582 - kfree(fc); 1583 - goto err; 1584 - } 1585 - 1586 - fuse_conn_init(fc, fm, sb->s_user_ns, &fuse_dev_fiq_ops, NULL); 1587 - fc->release = fuse_free_conn; 1588 - 1589 - sb->s_fs_info = fm; 1590 1587 1591 1588 err = fuse_fill_super_common(sb, ctx); 1592 1589 if (err) 1593 - goto err_put_conn; 1590 + return err; 1594 1591 /* file->private_data shall be visible on all CPUs after this */ 1595 1592 smp_mb(); 1596 1593 fuse_send_init(get_fuse_mount_super(sb)); 1597 1594 return 0; 1598 - 1599 - err_put_conn: 1600 - fuse_conn_put(fc); 1601 - kfree(fm); 1602 - sb->s_fs_info = NULL; 1603 - err: 1604 - return err; 1605 1595 } 1606 1596 1607 1597 /* ··· 1599 1637 { 1600 1638 struct fuse_fs_context *ctx = fsc->fs_private; 1601 1639 struct fuse_dev *fud; 1640 + struct fuse_conn *fc; 1641 + struct fuse_mount *fm; 1602 1642 struct super_block *sb; 1603 1643 int err; 1644 + 1645 + fc = kmalloc(sizeof(*fc), GFP_KERNEL); 1646 + if (!fc) 1647 + return -ENOMEM; 1648 + 1649 + fm = kzalloc(sizeof(*fm), GFP_KERNEL); 1650 + if (!fm) { 1651 + kfree(fc); 1652 + return -ENOMEM; 1653 + } 1654 + 1655 + fuse_conn_init(fc, fm, fsc->user_ns, &fuse_dev_fiq_ops, NULL); 1656 + fc->release = fuse_free_conn; 1657 + 1658 + fsc->s_fs_info = fm; 1604 1659 1605 1660 if (ctx->fd_present) 1606 1661 ctx->file = fget(ctx->fd); 1607 1662 1608 1663 if (IS_ENABLED(CONFIG_BLOCK) && ctx->is_bdev) { 1609 1664 err = get_tree_bdev(fsc, fuse_fill_super); 1610 - goto out_fput; 1665 + goto out; 1611 1666 } 1612 1667 /* 1613 1668 * While block dev mount can be initialized with a dummy device fd 1614 1669 * (found by device name), normal fuse mounts can't 1615 1670 */ 1671 + err = -EINVAL; 1616 1672 if (!ctx->file) 1617 - return -EINVAL; 1673 + goto out; 1618 1674 1619 1675 /* 1620 1676 * Allow creating a fuse mount with an already initialized fuse ··· 1648 1668 } else { 1649 1669 err = get_tree_nodev(fsc, fuse_fill_super); 1650 1670 } 1651 - out_fput: 1671 + out: 1672 + if (fsc->s_fs_info) 1673 + fuse_mount_destroy(fm); 1652 1674 if (ctx->file) 1653 1675 fput(ctx->file); 1654 1676 return err; ··· 1729 1747 struct fuse_mount *fm = get_fuse_mount_super(sb); 1730 1748 bool last; 1731 1749 1732 - if (fm) { 1750 + if (sb->s_root) { 1733 1751 last = fuse_mount_remove(fm); 1734 1752 if (last) 1735 1753 fuse_conn_destroy(fm); 1736 1754 } 1737 1755 } 1738 1756 1757 + void fuse_mount_destroy(struct fuse_mount *fm) 1758 + { 1759 + fuse_conn_put(fm->fc); 1760 + kfree(fm); 1761 + } 1762 + EXPORT_SYMBOL(fuse_mount_destroy); 1763 + 1739 1764 static void fuse_kill_sb_anon(struct super_block *sb) 1740 1765 { 1741 1766 fuse_sb_destroy(sb); 1742 1767 kill_anon_super(sb); 1768 + fuse_mount_destroy(get_fuse_mount_super(sb)); 1743 1769 } 1744 1770 1745 1771 static struct file_system_type fuse_fs_type = { ··· 1765 1775 { 1766 1776 fuse_sb_destroy(sb); 1767 1777 kill_block_super(sb); 1778 + fuse_mount_destroy(get_fuse_mount_super(sb)); 1768 1779 } 1769 1780 1770 1781 static struct file_system_type fuseblk_fs_type = {
+4 -8
fs/fuse/virtio_fs.c
··· 1394 1394 bool last; 1395 1395 1396 1396 /* If mount failed, we can still be called without any fc */ 1397 - if (fm) { 1397 + if (sb->s_root) { 1398 1398 last = fuse_mount_remove(fm); 1399 1399 if (last) 1400 1400 virtio_fs_conn_destroy(fm); 1401 1401 } 1402 1402 kill_anon_super(sb); 1403 + fuse_mount_destroy(fm); 1403 1404 } 1404 1405 1405 1406 static int virtio_fs_test_super(struct super_block *sb, ··· 1456 1455 1457 1456 fsc->s_fs_info = fm; 1458 1457 sb = sget_fc(fsc, virtio_fs_test_super, set_anon_super_fc); 1459 - if (fsc->s_fs_info) { 1460 - fuse_conn_put(fc); 1461 - kfree(fm); 1462 - } 1458 + if (fsc->s_fs_info) 1459 + fuse_mount_destroy(fm); 1463 1460 if (IS_ERR(sb)) 1464 1461 return PTR_ERR(sb); 1465 1462 1466 1463 if (!sb->s_root) { 1467 1464 err = virtio_fs_fill_super(sb, fsc); 1468 1465 if (err) { 1469 - fuse_conn_put(fc); 1470 - kfree(fm); 1471 - sb->s_fs_info = NULL; 1472 1466 deactivate_locked_super(sb); 1473 1467 return err; 1474 1468 }