[ Sorry David, the complain script uses git blame and it just picked
you. And then I decided to keep the address because your email is
still active and you seem like an expert. -dan ]
Hello David Sterba,
The patch a1ee73626844: "btrfs: do an allocation earlier during
snapshot creation" from Nov 10, 2015, leads to the following static
checker warning:
fs/btrfs/ioctl.c:890 create_snapshot()
warn: 'pending_snapshot' not removed from list
fs/btrfs/ioctl.c
809
810 pending_snapshot = kzalloc(sizeof(*pending_snapshot),
GFP_KERNEL);
^^^^^^^^^^^^^^^^
Allocated here.
811 if (!pending_snapshot)
812 return -ENOMEM;
813
814 ret = get_anon_bdev(&pending_snapshot->anon_dev);
815 if (ret < 0)
816 goto free_pending;
817 pending_snapshot->root_item = kzalloc(sizeof(struct
btrfs_root_item),
818 GFP_KERNEL);
819 pending_snapshot->path = btrfs_alloc_path();
820 if (!pending_snapshot->root_item || !pending_snapshot->path) {
821 ret = -ENOMEM;
822 goto free_pending;
823 }
824
825 btrfs_init_block_rsv(&pending_snapshot->block_rsv,
826 BTRFS_BLOCK_RSV_TEMP);
827 /*
828 * 1 - parent dir inode
829 * 2 - dir entries
830 * 1 - root item
831 * 2 - root ref/backref
832 * 1 - root of snapshot
833 * 1 - UUID item
834 */
835 ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root,
836 &pending_snapshot->block_rsv, 8,
837 false);
838 if (ret)
839 goto free_pending;
840
841 pending_snapshot->dentry = dentry;
842 pending_snapshot->root = root;
843 pending_snapshot->readonly = readonly;
844 pending_snapshot->dir = dir;
845 pending_snapshot->inherit = inherit;
846
847 trans = btrfs_start_transaction(root, 0);
848 if (IS_ERR(trans)) {
849 ret = PTR_ERR(trans);
850 goto fail;
851 }
852
853 spin_lock(&fs_info->trans_lock);
854 list_add(&pending_snapshot->list,
855 &trans->transaction->pending_snapshots);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Added to the list here.
856 spin_unlock(&fs_info->trans_lock);
857
858 ret = btrfs_commit_transaction(trans);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This will clean empty the ->pending_snapshots list when we call
create_pending_snapshots() but it's possible to fail before that
happens.
Possibly one fix would be to clear out the ->pending_snapshots list in
the __btrfs_end_transaction() function.
859 if (ret)
860 goto fail;
861
862 ret = pending_snapshot->error;
863 if (ret)
864 goto fail;
865
866 ret = btrfs_orphan_cleanup(pending_snapshot->snap);
867 if (ret)
868 goto fail;
869
870 inode = btrfs_lookup_dentry(d_inode(dentry->d_parent), dentry);
871 if (IS_ERR(inode)) {
872 ret = PTR_ERR(inode);
873 goto fail;
874 }
875
876 d_instantiate(dentry, inode);
877 ret = 0;
878 pending_snapshot->anon_dev = 0;
879 fail:
880 /* Prevent double freeing of anon_dev */
881 if (ret && pending_snapshot->snap)
882 pending_snapshot->snap->anon_dev = 0;
883 btrfs_put_root(pending_snapshot->snap);
884 btrfs_subvolume_release_metadata(root,
&pending_snapshot->block_rsv);
885 free_pending:
886 if (pending_snapshot->anon_dev)
887 free_anon_bdev(pending_snapshot->anon_dev);
888 kfree(pending_snapshot->root_item);
889 btrfs_free_path(pending_snapshot->path);
890 kfree(pending_snapshot);
^^^^^^^^^^^^^^^^^^^^^^^
If btrfs_commit_transaction() fails too early then this is freed but
it's still in the ->pending_snapshots list leading to a use after free.
891
892 return ret;
893 }
regards,
dan carpenter